Initial Commit
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright Rene Rivera 2008-2015
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PREDEF_ARCHITECTURE_IA64_H
|
||||
#define BOOST_PREDEF_ARCHITECTURE_IA64_H
|
||||
|
||||
#include <boost/predef/version_number.h>
|
||||
#include <boost/predef/make.h>
|
||||
|
||||
/*`
|
||||
[heading `BOOST_ARCH_IA64`]
|
||||
|
||||
[@http://en.wikipedia.org/wiki/Ia64 Intel Itanium 64] architecture.
|
||||
|
||||
[table
|
||||
[[__predef_symbol__] [__predef_version__]]
|
||||
|
||||
[[`__ia64__`] [__predef_detection__]]
|
||||
[[`_IA64`] [__predef_detection__]]
|
||||
[[`__IA64__`] [__predef_detection__]]
|
||||
[[`__ia64`] [__predef_detection__]]
|
||||
[[`_M_IA64`] [__predef_detection__]]
|
||||
[[`__itanium__`] [__predef_detection__]]
|
||||
]
|
||||
*/
|
||||
|
||||
#define BOOST_ARCH_IA64 BOOST_VERSION_NUMBER_NOT_AVAILABLE
|
||||
|
||||
#if defined(__ia64__) || defined(_IA64) || \
|
||||
defined(__IA64__) || defined(__ia64) || \
|
||||
defined(_M_IA64) || defined(__itanium__)
|
||||
# undef BOOST_ARCH_IA64
|
||||
# define BOOST_ARCH_IA64 BOOST_VERSION_NUMBER_AVAILABLE
|
||||
#endif
|
||||
|
||||
#if BOOST_ARCH_IA64
|
||||
# define BOOST_ARCH_IA64_AVAILABLE
|
||||
#endif
|
||||
|
||||
#define BOOST_ARCH_IA64_NAME "Intel Itanium 64"
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/predef/detail/test.h>
|
||||
BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_IA64,BOOST_ARCH_IA64_NAME)
|
||||
@@ -0,0 +1,12 @@
|
||||
// Boost.Function library
|
||||
|
||||
// Copyright Douglas Gregor 2002-2003. 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)
|
||||
|
||||
// For more information, see http://www.boost.org
|
||||
|
||||
#define BOOST_FUNCTION_NUM_ARGS 10
|
||||
#include <boost/function/detail/maybe_include.hpp>
|
||||
#undef BOOST_FUNCTION_NUM_ARGS
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,143 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
#if !defined(FUSION_AS_MAP_0932005_1339)
|
||||
#define FUSION_AS_MAP_0932005_1339
|
||||
|
||||
#include <boost/preprocessor/iterate.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/inc.hpp>
|
||||
#include <boost/preprocessor/dec.hpp>
|
||||
#include <boost/fusion/container/map/detail/cpp03/map.hpp>
|
||||
#include <boost/fusion/iterator/value_of.hpp>
|
||||
#include <boost/fusion/iterator/deref.hpp>
|
||||
#include <boost/fusion/iterator/next.hpp>
|
||||
|
||||
namespace boost { namespace fusion { namespace detail
|
||||
{
|
||||
BOOST_FUSION_BARRIER_BEGIN
|
||||
|
||||
template <int size, bool is_assoc>
|
||||
struct as_map;
|
||||
|
||||
template <bool is_assoc>
|
||||
struct as_map<0, is_assoc>
|
||||
{
|
||||
template <typename Iterator>
|
||||
struct apply
|
||||
{
|
||||
typedef map<> type;
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static typename apply<Iterator>::type
|
||||
call(Iterator)
|
||||
{
|
||||
return map<>();
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_FUSION_BARRIER_END
|
||||
}}}
|
||||
|
||||
#if !defined(BOOST_FUSION_DONT_USE_PREPROCESSED_FILES)
|
||||
#include <boost/fusion/container/map/detail/cpp03/preprocessed/as_map.hpp>
|
||||
#else
|
||||
#if defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES)
|
||||
#pragma wave option(preserve: 2, line: 0, output: "preprocessed/as_map" FUSION_MAX_MAP_SIZE_STR ".hpp")
|
||||
#endif
|
||||
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
This is an auto-generated file. Do not edit!
|
||||
==============================================================================*/
|
||||
|
||||
#if defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES)
|
||||
#pragma wave option(preserve: 1)
|
||||
#endif
|
||||
|
||||
namespace boost { namespace fusion { namespace detail
|
||||
{
|
||||
BOOST_FUSION_BARRIER_BEGIN
|
||||
|
||||
#define BOOST_FUSION_NEXT_ITERATOR(z, n, data) \
|
||||
typedef typename fusion::result_of::next<BOOST_PP_CAT(I, n)>::type \
|
||||
BOOST_PP_CAT(I, BOOST_PP_INC(n));
|
||||
|
||||
#define BOOST_FUSION_NEXT_CALL_ITERATOR(z, n, data) \
|
||||
typename gen::BOOST_PP_CAT(I, BOOST_PP_INC(n)) \
|
||||
BOOST_PP_CAT(i, BOOST_PP_INC(n)) = fusion::next(BOOST_PP_CAT(i, n));
|
||||
|
||||
#define BOOST_FUSION_PAIR_FROM_ITERATOR(z, n, data) \
|
||||
typedef pair_from<BOOST_PP_CAT(I, n), is_assoc> BOOST_PP_CAT(D, n); \
|
||||
typedef typename BOOST_PP_CAT(D, n)::type BOOST_PP_CAT(T, n);
|
||||
|
||||
#define BOOST_FUSION_DREF_CALL_ITERATOR(z, n, data) \
|
||||
gen::BOOST_PP_CAT(D, n)::call(BOOST_PP_CAT(i, n))
|
||||
|
||||
#define BOOST_PP_FILENAME_1 <boost/fusion/container/map/detail/cpp03/as_map.hpp>
|
||||
#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_MAP_SIZE)
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
#undef BOOST_FUSION_NEXT_ITERATOR
|
||||
#undef BOOST_FUSION_NEXT_CALL_ITERATOR
|
||||
#undef BOOST_FUSION_PAIR_FROM_ITERATOR
|
||||
#undef BOOST_FUSION_DREF_CALL_ITERATOR
|
||||
|
||||
BOOST_FUSION_BARRIER_END
|
||||
}}}
|
||||
|
||||
#if defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES)
|
||||
#pragma wave option(output: null)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FUSION_DONT_USE_PREPROCESSED_FILES
|
||||
|
||||
#endif
|
||||
#else // defined(BOOST_PP_IS_ITERATING)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Preprocessor vertical repetition code
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define N BOOST_PP_ITERATION()
|
||||
|
||||
template <bool is_assoc>
|
||||
struct as_map<N, is_assoc>
|
||||
{
|
||||
template <typename I0>
|
||||
struct apply
|
||||
{
|
||||
BOOST_PP_REPEAT(BOOST_PP_DEC(N), BOOST_FUSION_NEXT_ITERATOR, _)
|
||||
BOOST_PP_REPEAT(N, BOOST_FUSION_PAIR_FROM_ITERATOR, _)
|
||||
typedef map<BOOST_PP_ENUM_PARAMS(N, T)> type;
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static typename apply<Iterator>::type
|
||||
call(Iterator const& i0)
|
||||
{
|
||||
typedef apply<Iterator> gen;
|
||||
typedef typename gen::type result;
|
||||
BOOST_PP_REPEAT(BOOST_PP_DEC(N), BOOST_FUSION_NEXT_CALL_ITERATOR, _)
|
||||
return result(BOOST_PP_ENUM(N, BOOST_FUSION_DREF_CALL_ITERATOR, _));
|
||||
}
|
||||
};
|
||||
|
||||
#undef N
|
||||
#endif // defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
/*==============================================================================
|
||||
Copyright (c) 2013 Jamboree
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#ifndef BOOST_FUSION_FLATTEN_VIEW_ITERATOR_HPP_INCLUDED
|
||||
#define BOOST_FUSION_FLATTEN_VIEW_ITERATOR_HPP_INCLUDED
|
||||
|
||||
|
||||
#include <boost/fusion/support/config.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/fusion/container/list/cons.hpp>
|
||||
#include <boost/fusion/support/unused.hpp>
|
||||
#include <boost/fusion/include/equal_to.hpp>
|
||||
#include <boost/fusion/iterator/next.hpp>
|
||||
#include <boost/fusion/iterator/deref.hpp>
|
||||
#include <boost/fusion/iterator/value_of.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace fusion
|
||||
{
|
||||
struct forward_traversal_tag;
|
||||
struct flatten_view_iterator_tag;
|
||||
|
||||
template<class First, class Base>
|
||||
struct flatten_view_iterator
|
||||
: iterator_base<flatten_view_iterator<First, Base> >
|
||||
{
|
||||
typedef flatten_view_iterator_tag fusion_tag;
|
||||
typedef forward_traversal_tag category;
|
||||
|
||||
typedef convert_iterator<First> first_converter;
|
||||
typedef typename first_converter::type first_type;
|
||||
typedef Base base_type;
|
||||
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
flatten_view_iterator(First const& first, Base const& base)
|
||||
: first(first), base(base)
|
||||
{}
|
||||
|
||||
first_type first;
|
||||
base_type base;
|
||||
};
|
||||
}}
|
||||
|
||||
namespace boost { namespace fusion { namespace detail
|
||||
{
|
||||
template<class Iterator, class = void>
|
||||
struct make_descent_cons
|
||||
{
|
||||
typedef cons<Iterator> type;
|
||||
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static inline type apply(Iterator const& it)
|
||||
{
|
||||
return type(it);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Iterator>
|
||||
struct make_descent_cons<Iterator,
|
||||
typename enable_if<traits::is_sequence<
|
||||
typename result_of::value_of<Iterator>::type> >::type>
|
||||
{
|
||||
// we use 'value_of' above for convenience, assuming the value won't be reference,
|
||||
// while we must use the regular 'deref' here for const issues...
|
||||
typedef typename
|
||||
remove_reference<typename result_of::deref<Iterator>::type>::type
|
||||
sub_sequence;
|
||||
|
||||
typedef typename
|
||||
result_of::begin<sub_sequence>::type
|
||||
sub_begin;
|
||||
|
||||
typedef cons<Iterator, typename make_descent_cons<sub_begin>::type> type;
|
||||
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static inline type apply(Iterator const& it)
|
||||
{
|
||||
return type(it, make_descent_cons<sub_begin>::apply(
|
||||
fusion::begin(*it)));
|
||||
}
|
||||
};
|
||||
|
||||
template<class Cons, class Base>
|
||||
struct build_flatten_view_iterator;
|
||||
|
||||
template<class Car, class Base>
|
||||
struct build_flatten_view_iterator<cons<Car>, Base>
|
||||
{
|
||||
typedef flatten_view_iterator<Car, Base> type;
|
||||
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static inline type apply(cons<Car> const& cons, Base const& base)
|
||||
{
|
||||
return type(cons.car, base);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Car, class Cdr, class Base>
|
||||
struct build_flatten_view_iterator<cons<Car, Cdr>, Base>
|
||||
{
|
||||
typedef flatten_view_iterator<Car, Base> next_base;
|
||||
typedef build_flatten_view_iterator<Cdr, next_base> next;
|
||||
typedef typename next::type type;
|
||||
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static inline type apply(cons<Car, Cdr> const& cons, Base const& base)
|
||||
{
|
||||
return next::apply(cons.cdr, next_base(cons.car, base));
|
||||
}
|
||||
};
|
||||
|
||||
template<class Base, class Iterator, class = void>
|
||||
struct seek_descent
|
||||
{
|
||||
typedef make_descent_cons<Iterator> make_descent_cons_;
|
||||
typedef typename make_descent_cons_::type cons_type;
|
||||
typedef
|
||||
build_flatten_view_iterator<cons_type, Base>
|
||||
build_flatten_view_iterator_;
|
||||
typedef typename build_flatten_view_iterator_::type type;
|
||||
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static inline type apply(Base const& base, Iterator const& it)
|
||||
{
|
||||
return build_flatten_view_iterator_::apply(
|
||||
make_descent_cons_::apply(it), base);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Base, class Iterator>
|
||||
struct seek_descent<Base, Iterator,
|
||||
typename enable_if<
|
||||
result_of::equal_to<Iterator, typename result_of::end<
|
||||
typename result_of::value_of<Base>::type>::type> >::type>
|
||||
{
|
||||
typedef typename result_of::next<Base>::type type;
|
||||
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static inline type apply(Base const& base, Iterator const&)
|
||||
{
|
||||
return fusion::next(base);
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
namespace boost { namespace fusion { namespace extension
|
||||
{
|
||||
template<>
|
||||
struct next_impl<flatten_view_iterator_tag>
|
||||
{
|
||||
template<typename Iterator>
|
||||
struct apply
|
||||
{
|
||||
typedef typename Iterator::first_type first_type;
|
||||
typedef typename Iterator::base_type base_type;
|
||||
typedef typename result_of::next<first_type>::type next_type;
|
||||
|
||||
typedef detail::seek_descent<base_type, next_type> seek_descent;
|
||||
typedef typename seek_descent::type type;
|
||||
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static inline
|
||||
type call(Iterator const& it)
|
||||
{
|
||||
return seek_descent::apply(it.base, fusion::next(it.first));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct deref_impl<flatten_view_iterator_tag>
|
||||
{
|
||||
template<typename Iterator>
|
||||
struct apply
|
||||
{
|
||||
typedef typename
|
||||
result_of::deref<typename Iterator::first_type>::type
|
||||
type;
|
||||
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static inline
|
||||
type call(Iterator const& it)
|
||||
{
|
||||
return *it.first;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct value_of_impl<flatten_view_iterator_tag>
|
||||
{
|
||||
template<typename Iterator>
|
||||
struct apply
|
||||
{
|
||||
typedef typename
|
||||
result_of::value_of<typename Iterator::first_type>::type
|
||||
type;
|
||||
};
|
||||
};
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_FUSION_WORKAROUND_FOR_LWG_2408
|
||||
namespace std
|
||||
{
|
||||
template <typename First, typename Base>
|
||||
struct iterator_traits< ::boost::fusion::flatten_view_iterator<First, Base> >
|
||||
{ };
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Dummy>
|
||||
struct function_ptr_impl<2, Dummy>
|
||||
{
|
||||
template <typename RT, typename FP>
|
||||
struct impl
|
||||
{
|
||||
typedef RT result_type;
|
||||
impl(FP fp_)
|
||||
: fp(fp_) {}
|
||||
template <typename A0 , typename A1>
|
||||
RT operator()(A0 & a0 , A1 & a1) const
|
||||
{
|
||||
return fp(a0 , a1);
|
||||
}
|
||||
FP fp;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Dummy>
|
||||
struct function_ptr_impl<3, Dummy>
|
||||
{
|
||||
template <typename RT, typename FP>
|
||||
struct impl
|
||||
{
|
||||
typedef RT result_type;
|
||||
impl(FP fp_)
|
||||
: fp(fp_) {}
|
||||
template <typename A0 , typename A1 , typename A2>
|
||||
RT operator()(A0 & a0 , A1 & a1 , A2 & a2) const
|
||||
{
|
||||
return fp(a0 , a1 , a2);
|
||||
}
|
||||
FP fp;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Dummy>
|
||||
struct function_ptr_impl<4, Dummy>
|
||||
{
|
||||
template <typename RT, typename FP>
|
||||
struct impl
|
||||
{
|
||||
typedef RT result_type;
|
||||
impl(FP fp_)
|
||||
: fp(fp_) {}
|
||||
template <typename A0 , typename A1 , typename A2 , typename A3>
|
||||
RT operator()(A0 & a0 , A1 & a1 , A2 & a2 , A3 & a3) const
|
||||
{
|
||||
return fp(a0 , a1 , a2 , a3);
|
||||
}
|
||||
FP fp;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Dummy>
|
||||
struct function_ptr_impl<5, Dummy>
|
||||
{
|
||||
template <typename RT, typename FP>
|
||||
struct impl
|
||||
{
|
||||
typedef RT result_type;
|
||||
impl(FP fp_)
|
||||
: fp(fp_) {}
|
||||
template <typename A0 , typename A1 , typename A2 , typename A3 , typename A4>
|
||||
RT operator()(A0 & a0 , A1 & a1 , A2 & a2 , A3 & a3 , A4 & a4) const
|
||||
{
|
||||
return fp(a0 , a1 , a2 , a3 , a4);
|
||||
}
|
||||
FP fp;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Dummy>
|
||||
struct function_ptr_impl<6, Dummy>
|
||||
{
|
||||
template <typename RT, typename FP>
|
||||
struct impl
|
||||
{
|
||||
typedef RT result_type;
|
||||
impl(FP fp_)
|
||||
: fp(fp_) {}
|
||||
template <typename A0 , typename A1 , typename A2 , typename A3 , typename A4 , typename A5>
|
||||
RT operator()(A0 & a0 , A1 & a1 , A2 & a2 , A3 & a3 , A4 & a4 , A5 & a5) const
|
||||
{
|
||||
return fp(a0 , a1 , a2 , a3 , a4 , a5);
|
||||
}
|
||||
FP fp;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Dummy>
|
||||
struct function_ptr_impl<7, Dummy>
|
||||
{
|
||||
template <typename RT, typename FP>
|
||||
struct impl
|
||||
{
|
||||
typedef RT result_type;
|
||||
impl(FP fp_)
|
||||
: fp(fp_) {}
|
||||
template <typename A0 , typename A1 , typename A2 , typename A3 , typename A4 , typename A5 , typename A6>
|
||||
RT operator()(A0 & a0 , A1 & a1 , A2 & a2 , A3 & a3 , A4 & a4 , A5 & a5 , A6 & a6) const
|
||||
{
|
||||
return fp(a0 , a1 , a2 , a3 , a4 , a5 , a6);
|
||||
}
|
||||
FP fp;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Dummy>
|
||||
struct function_ptr_impl<8, Dummy>
|
||||
{
|
||||
template <typename RT, typename FP>
|
||||
struct impl
|
||||
{
|
||||
typedef RT result_type;
|
||||
impl(FP fp_)
|
||||
: fp(fp_) {}
|
||||
template <typename A0 , typename A1 , typename A2 , typename A3 , typename A4 , typename A5 , typename A6 , typename A7>
|
||||
RT operator()(A0 & a0 , A1 & a1 , A2 & a2 , A3 & a3 , A4 & a4 , A5 & a5 , A6 & a6 , A7 & a7) const
|
||||
{
|
||||
return fp(a0 , a1 , a2 , a3 , a4 , a5 , a6 , a7);
|
||||
}
|
||||
FP fp;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Dummy>
|
||||
struct function_ptr_impl<9, Dummy>
|
||||
{
|
||||
template <typename RT, typename FP>
|
||||
struct impl
|
||||
{
|
||||
typedef RT result_type;
|
||||
impl(FP fp_)
|
||||
: fp(fp_) {}
|
||||
template <typename A0 , typename A1 , typename A2 , typename A3 , typename A4 , typename A5 , typename A6 , typename A7 , typename A8>
|
||||
RT operator()(A0 & a0 , A1 & a1 , A2 & a2 , A3 & a3 , A4 & a4 , A5 & a5 , A6 & a6 , A7 & a7 , A8 & a8) const
|
||||
{
|
||||
return fp(a0 , a1 , a2 , a3 , a4 , a5 , a6 , a7 , a8);
|
||||
}
|
||||
FP fp;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Dummy>
|
||||
struct function_ptr_impl<10, Dummy>
|
||||
{
|
||||
template <typename RT, typename FP>
|
||||
struct impl
|
||||
{
|
||||
typedef RT result_type;
|
||||
impl(FP fp_)
|
||||
: fp(fp_) {}
|
||||
template <typename A0 , typename A1 , typename A2 , typename A3 , typename A4 , typename A5 , typename A6 , typename A7 , typename A8 , typename A9>
|
||||
RT operator()(A0 & a0 , A1 & a1 , A2 & a2 , A3 & a3 , A4 & a4 , A5 & a5 , A6 & a6 , A7 & a7 , A8 & a8 , A9 & a9) const
|
||||
{
|
||||
return fp(a0 , a1 , a2 , a3 , a4 , a5 , a6 , a7 , a8 , a9);
|
||||
}
|
||||
FP fp;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright Christopher Kormanyos 2014.
|
||||
// Copyright John Maddock 2014.
|
||||
// Copyright Paul Bristow 2014.
|
||||
// Distributed under the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Implement quadruple-precision (and extended) support for <complex>.
|
||||
|
||||
#ifndef _BOOST_CSTDFLOAT_COMPLEX_2014_02_15_HPP_
|
||||
#define _BOOST_CSTDFLOAT_COMPLEX_2014_02_15_HPP_
|
||||
|
||||
#include <boost/math/cstdfloat/cstdfloat_types.hpp>
|
||||
#include <boost/math/cstdfloat/cstdfloat_limits.hpp>
|
||||
#include <boost/math/cstdfloat/cstdfloat_cmath.hpp>
|
||||
#include <boost/math/cstdfloat/cstdfloat_iostream.hpp>
|
||||
|
||||
#if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS)
|
||||
#error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS defined.
|
||||
#endif
|
||||
#if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH)
|
||||
#error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH defined.
|
||||
#endif
|
||||
#if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_IOSTREAM)
|
||||
#error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_IOSTREAM defined.
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
|
||||
|
||||
#define BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE boost::math::cstdfloat::detail::float_internal128_t
|
||||
#include <boost/math/cstdfloat/cstdfloat_complex_std.hpp>
|
||||
#undef BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE
|
||||
|
||||
#endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
|
||||
|
||||
#endif // _BOOST_CSTDFLOAT_COMPLEX_2014_02_15_HPP_
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (C) 2013 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// 2013/10 Vicente J. Botet Escriba
|
||||
// Creation.
|
||||
|
||||
#ifndef BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP
|
||||
#define BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP
|
||||
|
||||
#include <boost/thread/csbl/memory/config.hpp>
|
||||
|
||||
// 20.7.6, allocator argument tag
|
||||
#if defined BOOST_NO_CXX11_ALLOCATOR
|
||||
#include <boost/container/scoped_allocator.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::boost::container::allocator_arg_t;
|
||||
using ::boost::container::allocator_arg;
|
||||
}
|
||||
}
|
||||
#else
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::std::allocator_arg_t;
|
||||
using ::std::allocator_arg;
|
||||
}
|
||||
}
|
||||
#endif // BOOST_NO_CXX11_ALLOCATOR
|
||||
namespace boost
|
||||
{
|
||||
using ::boost::csbl::allocator_arg_t;
|
||||
using ::boost::csbl::allocator_arg;
|
||||
}
|
||||
#endif // header
|
||||
@@ -0,0 +1,13 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2007 Joel de Guzman
|
||||
|
||||
Distributed under the 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(FUSION_INCLUDE_ITERATOR_BASE)
|
||||
#define FUSION_INCLUDE_ITERATOR_BASE
|
||||
|
||||
#include <boost/fusion/support/config.hpp>
|
||||
#include <boost/fusion/support/iterator_base.hpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
subroutine to_contest_msg(msg0,msg)
|
||||
|
||||
! If the message has "R grid4" istead of "grid4", remove the "R "
|
||||
! and substitute the diametrically opposite grid.
|
||||
|
||||
character*6 g1,g2
|
||||
character*22 msg0,msg
|
||||
logical isgrid
|
||||
isgrid(g1)=g1(1:1).ge.'A' .and. g1(1:1).le.'R' .and. g1(2:2).ge.'A' .and. &
|
||||
g1(2:2).le.'R' .and. g1(3:3).ge.'0' .and. g1(3:3).le.'9' .and. &
|
||||
g1(4:4).ge.'0' .and. g1(4:4).le.'9' .and. g1(1:4).ne.'RR73'
|
||||
|
||||
i0=index(msg0,' R ') + 3 !Check for ' R ' in message
|
||||
g1=msg0(i0:i0+3)//' '
|
||||
if(isgrid(g1)) then !Check for ' R grid'
|
||||
call grid2deg(g1,dlong,dlat)
|
||||
dlong=dlong+180.0
|
||||
if(dlong.gt.180.0) dlong=dlong-360.0
|
||||
dlat=-dlat
|
||||
call deg2grid(dlong,dlat,g2) !g2=antipodes grid
|
||||
msg=msg0(1:i0-3)//g2(1:4) !Send message with g2
|
||||
else
|
||||
msg=msg0
|
||||
endif
|
||||
|
||||
return
|
||||
end subroutine to_contest_msg
|
||||
@@ -0,0 +1,289 @@
|
||||
//
|
||||
// Copyright (c) Antony Polukhin, 2012-2016.
|
||||
//
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
|
||||
#define BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
|
||||
|
||||
/// \file compile_time_type_info.hpp
|
||||
/// \brief Contains helper macros and implementation details of boost::typeindex::ctti_type_index.
|
||||
/// Not intended for inclusion from user's code.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/// @cond
|
||||
#define BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(begin_skip, end_skip, runtime_skip, runtime_skip_until) \
|
||||
namespace boost { namespace typeindex { namespace detail { \
|
||||
BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_begin = begin_skip; \
|
||||
BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_end = end_skip; \
|
||||
BOOST_STATIC_CONSTEXPR bool ctti_skip_more_at_runtime = runtime_skip; \
|
||||
BOOST_STATIC_CONSTEXPR char ctti_skip_until_runtime[] = runtime_skip_until; \
|
||||
}}} /* namespace boost::typeindex::detail */ \
|
||||
/**/
|
||||
/// @endcond
|
||||
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
|
||||
/* Nothing to document. All the macro docs are moved to <boost/type_index.hpp> */
|
||||
#elif defined(BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING)
|
||||
# include <boost/preprocessor/facilities/expand.hpp>
|
||||
BOOST_PP_EXPAND( BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING )
|
||||
#elif defined(_MSC_VER) && defined (BOOST_NO_CXX11_NOEXCEPT)
|
||||
// sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void)") - 1
|
||||
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 10, false, "")
|
||||
#elif defined(_MSC_VER) && !defined (BOOST_NO_CXX11_NOEXCEPT)
|
||||
// sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void) noexcept") - 1
|
||||
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 19, false, "")
|
||||
#elif defined(__clang__) && defined(__APPLE__)
|
||||
// Someone made __clang_major__ equal to LLVM version rather than compiler version
|
||||
// on APPLE platform.
|
||||
//
|
||||
// Using less efficient solution because there is no good way to detect real version of Clang.
|
||||
// sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "???????????>::n() [T = int"
|
||||
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ")
|
||||
#elif defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ == 0))
|
||||
// sizeof("static const char *boost::detail::ctti<") - 1, sizeof(">::n()") - 1
|
||||
// note: checked on 3.0
|
||||
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 6, false, "")
|
||||
#elif defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ > 0))
|
||||
// sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "int>::n() [T = int"
|
||||
// note: checked on 3.1, 3.4
|
||||
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ")
|
||||
#elif defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
// sizeof("static contexpr char boost::detail::ctti<T>::s() [with unsigned int I = 0u; T = ") - 1, sizeof("]") - 1
|
||||
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(81, 1, false, "")
|
||||
#elif defined(__GNUC__) && defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
// sizeof("static const char* boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
|
||||
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "")
|
||||
#else
|
||||
// Deafult code for other platforms... Just skip nothing!
|
||||
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(0, 0, false, "")
|
||||
#endif
|
||||
|
||||
#undef BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS
|
||||
|
||||
namespace boost { namespace typeindex { namespace detail {
|
||||
template <bool Condition>
|
||||
BOOST_CXX14_CONSTEXPR inline void assert_compile_time_legths() BOOST_NOEXCEPT {
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
Condition,
|
||||
"TypeIndex library is misconfigured for your compiler. "
|
||||
"Please define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct values. See section "
|
||||
"'RTTI emulation limitations' of the documentation for more information."
|
||||
);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_CXX14_CONSTEXPR inline void failed_to_get_function_name() BOOST_NOEXCEPT {
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
sizeof(T) && false,
|
||||
"TypeIndex library could not detect your compiler. "
|
||||
"Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use "
|
||||
"correct compiler macro for getting the whole function name. "
|
||||
"Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that."
|
||||
);
|
||||
}
|
||||
|
||||
template <unsigned int ArrayLength>
|
||||
BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin, boost::mpl::false_) BOOST_NOEXCEPT {
|
||||
return begin;
|
||||
}
|
||||
|
||||
template<class ForwardIterator1, class ForwardIterator2>
|
||||
BOOST_CXX14_CONSTEXPR inline ForwardIterator1 constexpr_search(
|
||||
ForwardIterator1 first1,
|
||||
ForwardIterator1 last1,
|
||||
ForwardIterator2 first2,
|
||||
ForwardIterator2 last2) BOOST_NOEXCEPT
|
||||
{
|
||||
if (first2 == last2) {
|
||||
return first1; // specified in C++11
|
||||
}
|
||||
|
||||
while (first1 != last1) {
|
||||
ForwardIterator1 it1 = first1;
|
||||
ForwardIterator2 it2 = first2;
|
||||
|
||||
while (*it1 == *it2) {
|
||||
++it1;
|
||||
++it2;
|
||||
if (it2 == last2) return first1;
|
||||
if (it1 == last1) return last1;
|
||||
}
|
||||
|
||||
++first1;
|
||||
}
|
||||
|
||||
return last1;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp(const char *v1, const char *v2) BOOST_NOEXCEPT {
|
||||
while (*v1 != '\0' && *v1 == *v2) {
|
||||
++v1;
|
||||
++v2;
|
||||
};
|
||||
|
||||
return static_cast<int>(*v1) - *v2;
|
||||
}
|
||||
|
||||
template <unsigned int ArrayLength>
|
||||
BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin, boost::mpl::true_) BOOST_NOEXCEPT {
|
||||
const char* const it = constexpr_search(
|
||||
begin, begin + ArrayLength,
|
||||
ctti_skip_until_runtime, ctti_skip_until_runtime + sizeof(ctti_skip_until_runtime) - 1
|
||||
);
|
||||
return (it == begin + ArrayLength ? begin : it + sizeof(ctti_skip_until_runtime) - 1);
|
||||
}
|
||||
|
||||
template <unsigned int ArrayLength>
|
||||
BOOST_CXX14_CONSTEXPR inline const char* skip_begining(const char* begin) BOOST_NOEXCEPT {
|
||||
assert_compile_time_legths<(ArrayLength > ctti_skip_size_at_begin + ctti_skip_size_at_end)>();
|
||||
return skip_begining_runtime<ArrayLength - ctti_skip_size_at_begin>(
|
||||
begin + ctti_skip_size_at_begin,
|
||||
boost::mpl::bool_<ctti_skip_more_at_runtime>()
|
||||
);
|
||||
}
|
||||
|
||||
#if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
template <unsigned int... I>
|
||||
struct index_seq {};
|
||||
|
||||
template <typename Left, typename Right>
|
||||
struct make_index_sequence_join;
|
||||
|
||||
template <unsigned int... Left, unsigned int... Right>
|
||||
struct make_index_sequence_join<index_seq<Left...>, index_seq<Right...> > {
|
||||
typedef index_seq<Left..., Right...> type;
|
||||
};
|
||||
|
||||
template <unsigned int C, unsigned int D>
|
||||
struct make_index_seq_impl {
|
||||
typedef typename make_index_sequence_join<
|
||||
typename make_index_seq_impl<C, D / 2>::type,
|
||||
typename make_index_seq_impl<C + D / 2, (D + 1) / 2>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <unsigned int C>
|
||||
struct make_index_seq_impl<C, 0> {
|
||||
typedef index_seq<> type;
|
||||
};
|
||||
|
||||
template <unsigned int C>
|
||||
struct make_index_seq_impl<C, 1> {
|
||||
typedef index_seq<C> type;
|
||||
};
|
||||
|
||||
template <char... C>
|
||||
struct cstring {
|
||||
static constexpr unsigned int size_ = sizeof...(C);
|
||||
static constexpr char data_[size_] = { C... };
|
||||
};
|
||||
|
||||
template <char... C>
|
||||
constexpr char cstring<C...>::data_[];
|
||||
#endif
|
||||
|
||||
}}} // namespace boost::typeindex::detail
|
||||
|
||||
namespace boost { namespace detail {
|
||||
|
||||
/// Noncopyable type_info that does not require RTTI.
|
||||
/// CTTI == Compile Time Type Info.
|
||||
/// This name must be as short as possible, to avoid code bloat
|
||||
template <class T>
|
||||
struct ctti {
|
||||
|
||||
#if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
//helper functions
|
||||
template <unsigned int I>
|
||||
constexpr static char s() BOOST_NOEXCEPT { // step
|
||||
constexpr unsigned int offset =
|
||||
(I >= 10u ? 1u : 0u)
|
||||
+ (I >= 100u ? 1u : 0u)
|
||||
+ (I >= 1000u ? 1u : 0u)
|
||||
+ (I >= 10000u ? 1u : 0u)
|
||||
+ (I >= 100000u ? 1u : 0u)
|
||||
+ (I >= 1000000u ? 1u : 0u)
|
||||
;
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
|
||||
return BOOST_TYPE_INDEX_FUNCTION_SIGNATURE[I + offset];
|
||||
#elif defined(__FUNCSIG__)
|
||||
return __FUNCSIG__[I + offset];
|
||||
#else
|
||||
return __PRETTY_FUNCTION__[I + offset];
|
||||
#endif
|
||||
}
|
||||
|
||||
template <unsigned int ...Indexes>
|
||||
constexpr static const char* impl(::boost::typeindex::detail::index_seq<Indexes...> ) BOOST_NOEXCEPT {
|
||||
return ::boost::typeindex::detail::cstring<s<Indexes>()...>::data_;
|
||||
}
|
||||
|
||||
template <unsigned int D = 0> // `D` means `Dummy`
|
||||
constexpr static const char* n() BOOST_NOEXCEPT {
|
||||
#if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
|
||||
constexpr unsigned int size = sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE);
|
||||
#elif defined(__FUNCSIG__)
|
||||
constexpr unsigned int size = sizeof(__FUNCSIG__);
|
||||
#elif defined(__PRETTY_FUNCTION__) \
|
||||
|| defined(__GNUC__) \
|
||||
|| (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \
|
||||
|| (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \
|
||||
|| (defined(__ICC) && (__ICC >= 600)) \
|
||||
|| defined(__ghs__) \
|
||||
|| defined(__DMC__)
|
||||
constexpr unsigned int size = sizeof(__PRETTY_FUNCTION__);
|
||||
#else
|
||||
boost::typeindex::detail::failed_to_get_function_name();
|
||||
#endif
|
||||
|
||||
boost::typeindex::detail::assert_compile_time_legths<
|
||||
(size > boost::typeindex::detail::ctti_skip_size_at_begin + boost::typeindex::detail::ctti_skip_size_at_end + sizeof("const *") - 1)
|
||||
>();
|
||||
static_assert(!boost::typeindex::detail::ctti_skip_more_at_runtime, "Skipping for GCC in C++14 mode is unsupported");
|
||||
|
||||
typedef typename boost::typeindex::detail::make_index_seq_impl<
|
||||
boost::typeindex::detail::ctti_skip_size_at_begin,
|
||||
size - sizeof("const *") + 1 - boost::typeindex::detail::ctti_skip_size_at_begin
|
||||
>::type idx_seq;
|
||||
return impl(idx_seq());
|
||||
}
|
||||
#else
|
||||
/// Returns raw name. Must be as short, as possible, to avoid code bloat
|
||||
BOOST_CXX14_CONSTEXPR static const char* n() BOOST_NOEXCEPT {
|
||||
#if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
|
||||
return boost::typeindex::detail::skip_begining< sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) >(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE);
|
||||
#elif defined(__FUNCSIG__)
|
||||
return boost::typeindex::detail::skip_begining< sizeof(__FUNCSIG__) >(__FUNCSIG__);
|
||||
#elif defined(__PRETTY_FUNCTION__) \
|
||||
|| defined(__GNUC__) \
|
||||
|| (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \
|
||||
|| (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \
|
||||
|| (defined(__ICC) && (__ICC >= 600)) \
|
||||
|| defined(__ghs__) \
|
||||
|| defined(__DMC__)
|
||||
return boost::typeindex::detail::skip_begining< sizeof(__PRETTY_FUNCTION__) >(__PRETTY_FUNCTION__);
|
||||
#else
|
||||
boost::typeindex::detail::failed_to_get_function_name();
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
}} // namespace boost::detail
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// boost/cstdlib.hpp header ------------------------------------------------//
|
||||
|
||||
// Copyright Beman Dawes 2001. Distributed under the 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/utility/cstdlib.html for documentation.
|
||||
|
||||
// Revision History
|
||||
// 26 Feb 01 Initial version (Beman Dawes)
|
||||
|
||||
#ifndef BOOST_CSTDLIB_HPP
|
||||
#define BOOST_CSTDLIB_HPP
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
// The intent is to propose the following for addition to namespace std
|
||||
// in the C++ Standard Library, and to then deprecate EXIT_SUCCESS and
|
||||
// EXIT_FAILURE. As an implementation detail, this header defines the
|
||||
// new constants in terms of EXIT_SUCCESS and EXIT_FAILURE. In a new
|
||||
// standard, the constants would be implementation-defined, although it
|
||||
// might be worthwhile to "suggest" (which a standard is allowed to do)
|
||||
// values of 0 and 1 respectively.
|
||||
|
||||
// Rationale for having multiple failure values: some environments may
|
||||
// wish to distinguish between different classes of errors.
|
||||
// Rationale for choice of values: programs often use values < 100 for
|
||||
// their own error reporting. Values > 255 are sometimes reserved for
|
||||
// system detected errors. 200/201 were suggested to minimize conflict.
|
||||
|
||||
const int exit_success = EXIT_SUCCESS; // implementation-defined value
|
||||
const int exit_failure = EXIT_FAILURE; // implementation-defined value
|
||||
const int exit_exception_failure = 200; // otherwise uncaught exception
|
||||
const int exit_test_failure = 201; // report_error or
|
||||
// report_critical_error called.
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
// Status=review
|
||||
.Main Window:
|
||||
- Select *JT9+JT65* on the *Mode* menu.
|
||||
- Toggle the *Tx mode* button to read *Tx JT65*, and set the Tx and Rx
|
||||
frequencies to 1718 Hz.
|
||||
- Double-click on *Erase* to clear both text windows.
|
||||
|
||||
.Wide Graph Settings:
|
||||
|
||||
- *Bins/Pixel* = 7
|
||||
- *JT65 .... JT9* = 2500
|
||||
- Adjust the width of the Wide Graph window so that the upper
|
||||
frequency limit is approximately 4000 Hz.
|
||||
|
||||
.Open a Wave File:
|
||||
|
||||
- Select *File | Open* and navigate to +...\save\samples\JT9+JT65\130610_2343.wav+.
|
||||
The waterfall should look something like this:
|
||||
|
||||
//.130610_2343.wav Decode
|
||||
[[X14]]
|
||||
image::130610_2343-wav-80.png[align="left",alt="Wide Graph Decode 130610_2343"]
|
||||
|
||||
The position of the blue marker on the waterfall scale is
|
||||
set by the spinner control *JT65 nnnn JT9*, where nnnn is an audio
|
||||
frequency in Hz. In *JT9+JT65* mode the program will automatically
|
||||
decode JT9 signals only above this frequency. JT65 signals will be
|
||||
decoded over the full displayed frequency range.
|
||||
|
||||
JT9 signals appear in the *Cumulative* spectrum as nearly rectangular
|
||||
shapes about 16 Hz wide. They have no clearly visible sync tone like
|
||||
the one at the low-frequency edge of all JT65 signals. By convention
|
||||
the nominal frequency of both JT9 and JT65 signals is taken to be that
|
||||
of the lowest tone, at the left edge of its spectrum.
|
||||
|
||||
This sample file contains 17 decodable signals — nine in JT65 mode
|
||||
(flagged with the character # in the decoded text windows), and eight
|
||||
in JT9 mode (flagged with @). On multi-core computers the decoders
|
||||
for JT9 and JT65 modes run simultaneously, so their results will be
|
||||
interspersed. The *Band Activity* window contains all decodes (you
|
||||
might need to scroll back in the window to see some of them). A
|
||||
signal at the frequency specified by the green marker is given
|
||||
decoding priority, and its message is displayed also in the *Rx
|
||||
Frequency* window.
|
||||
|
||||
[[FigDecodes]]
|
||||
image::decodes.png[align="center"]
|
||||
|
||||
- Confirm that mouse-click behavior is similar to that described
|
||||
earlier, in <<TUT_EX1,Example 1>>. _WSJT-X_ automatically determines
|
||||
the mode of each JT9 or JT65 message.
|
||||
|
||||
TIP: When you double-click on a signal in the waterfall it will be
|
||||
properly decoded even if on the "`wrong`" side of the *JT65 nnnn JT9*
|
||||
marker. The Tx mode automatically switches to that of the decoded
|
||||
signal and the Rx and Tx frequency markers on the waterfall scale
|
||||
resize themselves accordingly. When selecting a JT65 signal, click on
|
||||
the sync tone at its left edge.
|
||||
|
||||
- Double-click on the waterfall near 815 Hz: a JT65 message
|
||||
originating from W7VP will be decoded and appear in the *Rx Frequency*
|
||||
window. Between the *UTC* and *Freq* columns on the decoded text line
|
||||
you will find *dB*, the measured signal-to-noise ratio, and *DT*, the
|
||||
signal's time offset in seconds relative to your computer clock.
|
||||
|
||||
[width="80%",align="center",cols="^10,2*^8,2*^10,54",options="header"]
|
||||
|===
|
||||
|UTC|dB|DT|Freq|Mode|Message
|
||||
|+2343+|+-7+|+0.3+|+815+|+#+|+KK4DSD W7VP -16+
|
||||
|===
|
||||
|
||||
- Double-click on the waterfall at 3196 Hz. The program will decode a
|
||||
JT9 message from IZ0MIT:
|
||||
|
||||
[width="80%",align="center",cols="^10,2*^8,2*^10,54",options="header"]
|
||||
|===
|
||||
|UTC|dB|DT|Freq|Mode|Message
|
||||
|+2343+|+-7+|+0.3+|+3196+|+@+|+WB8QPG IZ0MIT -11+
|
||||
|===
|
||||
|
||||
- Scroll back in the *Band Activity* window and double-click on the
|
||||
message `CQ DL7ACA JO40`. The program will set *Tx mode* to JT65 and Tx
|
||||
and Rx frequencies to that of DL7ACA, 975 Hz. If you had checked
|
||||
*Double-click on call sets Tx Enable* on the *Setup* menu, the program
|
||||
would configure itself to start a QSO with DL7ACA.
|
||||
|
||||
- Double-click on the decoded JT65 message `CQ TA4A KM37`. The program
|
||||
will set Tx mode to JT9 and the Rx and Tx frequencies to 3567 Hz. The
|
||||
program is now configured properly for a JT9 QSO with TA4A.
|
||||
|
||||
.Reopen the First Sample File:
|
||||
- Select *File | Open* and navigate to `...\save\samples\130418_1742.wav`.
|
||||
|
||||
Taking full advantage of the wide-band, dual-mode capability of
|
||||
_WSJT-X_ requires a receiver bandwidth of at least 4 kHz. These
|
||||
data were recorded with a much narrower Rx bandwidth, roughly 200 to
|
||||
2400 Hz. If you have no Rx filter wider than about 2.7 kHz, you will
|
||||
be using data like this. For best viewing, adjust *Bins/Pixel* and the
|
||||
width of the Wide Graph so that only the active part of the spectrum
|
||||
shows, say 200 to 2400 Hz. Re-open the example file after any change of
|
||||
*Bins/Pixel* or Wide Graph width, to refresh the waterfall.
|
||||
|
||||
The signals in this file are all JT9 signals. To decode them
|
||||
automatically in *JT9+JT65* mode you’ll need to move the *JT65 nnnn JT9*
|
||||
delimiter down to 1000 Hz or less.
|
||||
|
||||
.Waterfall Controls
|
||||
|
||||
Now is a good time to experiment with the *Start* control and the
|
||||
sliders controlling gain and zero-point of the waterfall and spectrum
|
||||
plots. *Start* determines the frequency displayed at the left side of
|
||||
the waterfall scale. Sliders set the baseline level and gain for the
|
||||
waterfall and the several types of spectra. Good starting values
|
||||
should be close to mid-scale. You might want to uncheck *Flatten*
|
||||
when adjusting the sliders. Re-open the wave file after each change,
|
||||
to see the new results.
|
||||
@@ -0,0 +1,46 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2014 Kohei Takahashi
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#ifndef FUSION_SET_FORWARD_11062014_1720
|
||||
#define FUSION_SET_FORWARD_11062014_1720
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/fusion/support/config.hpp>
|
||||
#include <boost/fusion/container/vector/detail/config.hpp>
|
||||
|
||||
#if !defined(BOOST_FUSION_HAS_VARIADIC_VECTOR) \
|
||||
|| (defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES))
|
||||
# if defined(BOOST_FUSION_HAS_VARIADIC_SET)
|
||||
# undef BOOST_FUSION_HAS_VARIADIC_SET
|
||||
# endif
|
||||
#else
|
||||
# if !defined(BOOST_FUSION_HAS_VARIADIC_SET)
|
||||
# define BOOST_FUSION_HAS_VARIADIC_SET
|
||||
# endif
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// With no variadics, we will use the C++03 version
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(BOOST_FUSION_HAS_VARIADIC_SET)
|
||||
# include <boost/fusion/container/set/detail/cpp03/set_fwd.hpp>
|
||||
#else
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// C++11 interface
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace fusion
|
||||
{
|
||||
struct set_tag;
|
||||
struct set_iterator_tag;
|
||||
|
||||
template <typename ...T>
|
||||
struct set;
|
||||
}}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
// (C) Copyright Douglas Gregor 2010
|
||||
//
|
||||
// Use, modification and distribution are 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 http://www.boost.org for most recent version.
|
||||
|
||||
// Clang compiler setup.
|
||||
|
||||
#define BOOST_HAS_PRAGMA_ONCE
|
||||
|
||||
// Detecting `-fms-extension` compiler flag assuming that _MSC_VER defined when that flag is used.
|
||||
#if defined (_MSC_VER) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 4))
|
||||
# define BOOST_HAS_PRAGMA_DETECT_MISMATCH
|
||||
#endif
|
||||
|
||||
// When compiling with clang before __has_extension was defined,
|
||||
// even if one writes 'defined(__has_extension) && __has_extension(xxx)',
|
||||
// clang reports a compiler error. So the only workaround found is:
|
||||
|
||||
#ifndef __has_extension
|
||||
#define __has_extension __has_feature
|
||||
#endif
|
||||
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_exceptions) && !defined(BOOST_NO_EXCEPTIONS)
|
||||
# define BOOST_NO_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_rtti) && !defined(BOOST_NO_RTTI)
|
||||
# define BOOST_NO_RTTI
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_rtti) && !defined(BOOST_NO_TYPEID)
|
||||
# define BOOST_NO_TYPEID
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_thread_local)
|
||||
# define BOOST_NO_CXX11_THREAD_LOCAL
|
||||
#endif
|
||||
|
||||
#ifdef __is_identifier
|
||||
#if !__is_identifier(__int64) && !defined(__GNUC__)
|
||||
# define BOOST_HAS_MS_INT64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __has_include(<stdint.h>)
|
||||
# define BOOST_HAS_STDINT_H
|
||||
#endif
|
||||
|
||||
|
||||
#define BOOST_HAS_NRVO
|
||||
|
||||
// Branch prediction hints
|
||||
#if defined(__has_builtin)
|
||||
#if __has_builtin(__builtin_expect)
|
||||
#define BOOST_LIKELY(x) __builtin_expect(x, 1)
|
||||
#define BOOST_UNLIKELY(x) __builtin_expect(x, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Clang supports "long long" in all compilation modes.
|
||||
#define BOOST_HAS_LONG_LONG
|
||||
|
||||
//
|
||||
// We disable this if the compiler is really nvcc with C++03 as it
|
||||
// doesn't actually support __int128 as of CUDA_VERSION=7500
|
||||
// even though it defines __SIZEOF_INT128__.
|
||||
// See https://svn.boost.org/trac/boost/ticket/10418
|
||||
// https://svn.boost.org/trac/boost/ticket/11852
|
||||
// Only re-enable this for nvcc if you're absolutely sure
|
||||
// of the circumstances under which it's supported.
|
||||
// Similarly __SIZEOF_INT128__ is defined when targetting msvc
|
||||
// compatibility even though the required support functions are absent.
|
||||
//
|
||||
#if defined(__CUDACC__)
|
||||
# if defined(BOOST_GCC_CXX11)
|
||||
# define BOOST_NVCC_CXX11
|
||||
# else
|
||||
# define BOOST_NVCC_CXX03
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__SIZEOF_INT128__) && !defined(BOOST_NVCC_CXX03) && !defined(_MSC_VER)
|
||||
# define BOOST_HAS_INT128
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// Dynamic shared object (DSO) and dynamic-link library (DLL) support
|
||||
//
|
||||
#if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32)
|
||||
# define BOOST_SYMBOL_EXPORT __attribute__((__visibility__("default")))
|
||||
# define BOOST_SYMBOL_IMPORT
|
||||
# define BOOST_SYMBOL_VISIBLE __attribute__((__visibility__("default")))
|
||||
#endif
|
||||
|
||||
//
|
||||
// The BOOST_FALLTHROUGH macro can be used to annotate implicit fall-through
|
||||
// between switch labels.
|
||||
//
|
||||
#if __cplusplus >= 201103L && defined(__has_warning)
|
||||
# if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
|
||||
# define BOOST_FALLTHROUGH [[clang::fallthrough]]
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_auto_type)
|
||||
# define BOOST_NO_CXX11_AUTO_DECLARATIONS
|
||||
# define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS
|
||||
#endif
|
||||
|
||||
//
|
||||
// Currently clang on Windows using VC++ RTL does not support C++11's char16_t or char32_t
|
||||
//
|
||||
#if (defined(_MSC_VER) && (_MSC_VER < 1900)) || !(defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L)
|
||||
# define BOOST_NO_CXX11_CHAR16_T
|
||||
# define BOOST_NO_CXX11_CHAR32_T
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1800) && !defined(__GNUC__)
|
||||
#define BOOST_HAS_EXPM1
|
||||
#define BOOST_HAS_LOG1P
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_constexpr)
|
||||
# define BOOST_NO_CXX11_CONSTEXPR
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_decltype)
|
||||
# define BOOST_NO_CXX11_DECLTYPE
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_decltype_incomplete_return_types)
|
||||
# define BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_defaulted_functions)
|
||||
# define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_deleted_functions)
|
||||
# define BOOST_NO_CXX11_DELETED_FUNCTIONS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_explicit_conversions)
|
||||
# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_default_function_template_args)
|
||||
# define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_generalized_initializers)
|
||||
# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_lambdas)
|
||||
# define BOOST_NO_CXX11_LAMBDAS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_local_type_template_args)
|
||||
# define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_noexcept)
|
||||
# define BOOST_NO_CXX11_NOEXCEPT
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_nullptr)
|
||||
# define BOOST_NO_CXX11_NULLPTR
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_range_for)
|
||||
# define BOOST_NO_CXX11_RANGE_BASED_FOR
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_raw_string_literals)
|
||||
# define BOOST_NO_CXX11_RAW_LITERALS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_reference_qualified_functions)
|
||||
# define BOOST_NO_CXX11_REF_QUALIFIERS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_generalized_initializers)
|
||||
# define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_rvalue_references)
|
||||
# define BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_strong_enums)
|
||||
# define BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_static_assert)
|
||||
# define BOOST_NO_CXX11_STATIC_ASSERT
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_alias_templates)
|
||||
# define BOOST_NO_CXX11_TEMPLATE_ALIASES
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_unicode_literals)
|
||||
# define BOOST_NO_CXX11_UNICODE_LITERALS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_variadic_templates)
|
||||
# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_user_literals)
|
||||
# define BOOST_NO_CXX11_USER_DEFINED_LITERALS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_alignas)
|
||||
# define BOOST_NO_CXX11_ALIGNAS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_trailing_return)
|
||||
# define BOOST_NO_CXX11_TRAILING_RESULT_TYPES
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_inline_namespaces)
|
||||
# define BOOST_NO_CXX11_INLINE_NAMESPACES
|
||||
#endif
|
||||
|
||||
#if !__has_feature(cxx_override_control)
|
||||
# define BOOST_NO_CXX11_FINAL
|
||||
#endif
|
||||
|
||||
#if !(__has_feature(__cxx_binary_literals__) || __has_extension(__cxx_binary_literals__))
|
||||
# define BOOST_NO_CXX14_BINARY_LITERALS
|
||||
#endif
|
||||
|
||||
#if !__has_feature(__cxx_decltype_auto__)
|
||||
# define BOOST_NO_CXX14_DECLTYPE_AUTO
|
||||
#endif
|
||||
|
||||
#if !__has_feature(__cxx_aggregate_nsdmi__)
|
||||
# define BOOST_NO_CXX14_AGGREGATE_NSDMI
|
||||
#endif
|
||||
|
||||
#if !__has_feature(__cxx_init_captures__)
|
||||
# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES
|
||||
#endif
|
||||
|
||||
#if !__has_feature(__cxx_generic_lambdas__)
|
||||
# define BOOST_NO_CXX14_GENERIC_LAMBDAS
|
||||
#endif
|
||||
|
||||
// clang < 3.5 has a defect with dependent type, like following.
|
||||
//
|
||||
// template <class T>
|
||||
// constexpr typename enable_if<pred<T> >::type foo(T &)
|
||||
// { } // error: no return statement in constexpr function
|
||||
//
|
||||
// This issue also affects C++11 mode, but C++11 constexpr requires return stmt.
|
||||
// Therefore we don't care such case.
|
||||
//
|
||||
// Note that we can't check Clang version directly as the numbering system changes depending who's
|
||||
// creating the Clang release (see https://github.com/boostorg/config/pull/39#issuecomment-59927873)
|
||||
// so instead verify that we have a feature that was introduced at the same time as working C++14
|
||||
// constexpr (generic lambda's in this case):
|
||||
//
|
||||
#if !__has_feature(__cxx_generic_lambdas__) || !__has_feature(__cxx_relaxed_constexpr__)
|
||||
# define BOOST_NO_CXX14_CONSTEXPR
|
||||
#endif
|
||||
|
||||
#if !__has_feature(__cxx_return_type_deduction__)
|
||||
# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION
|
||||
#endif
|
||||
|
||||
#if !__has_feature(__cxx_variable_templates__)
|
||||
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
|
||||
#endif
|
||||
|
||||
#if __cplusplus < 201400
|
||||
// All versions with __cplusplus above this value seem to support this:
|
||||
# define BOOST_NO_CXX14_DIGIT_SEPARATORS
|
||||
#endif
|
||||
//
|
||||
// __builtin_unreachable:
|
||||
#if defined(__has_builtin) && __has_builtin(__builtin_unreachable)
|
||||
#define BOOST_UNREACHABLE_RETURN(x) __builtin_unreachable();
|
||||
#endif
|
||||
|
||||
// Clang has supported the 'unused' attribute since the first release.
|
||||
#define BOOST_ATTRIBUTE_UNUSED __attribute__((__unused__))
|
||||
|
||||
#ifndef BOOST_COMPILER
|
||||
# define BOOST_COMPILER "Clang version " __clang_version__
|
||||
#endif
|
||||
|
||||
// Macro used to identify the Clang compiler.
|
||||
#define BOOST_CLANG 1
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2011 Eric Niebler
|
||||
|
||||
Distributed under the 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_FUSION_SINGLE_VIEW_ADVANCE_IMPL_JUL_07_2011_1348PM)
|
||||
#define BOOST_FUSION_SINGLE_VIEW_ADVANCE_IMPL_JUL_07_2011_1348PM
|
||||
|
||||
#include <boost/fusion/support/config.hpp>
|
||||
#include <boost/mpl/plus.hpp>
|
||||
|
||||
namespace boost { namespace fusion
|
||||
{
|
||||
struct single_view_iterator_tag;
|
||||
|
||||
template <typename SingleView, typename Pos>
|
||||
struct single_view_iterator;
|
||||
|
||||
namespace extension
|
||||
{
|
||||
template<typename Tag>
|
||||
struct advance_impl;
|
||||
|
||||
template<>
|
||||
struct advance_impl<single_view_iterator_tag>
|
||||
{
|
||||
template<typename Iterator, typename Dist>
|
||||
struct apply
|
||||
{
|
||||
typedef single_view_iterator<
|
||||
typename Iterator::single_view_type,
|
||||
typename mpl::plus<typename Iterator::position, Dist>::type>
|
||||
type;
|
||||
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static type
|
||||
call(Iterator const& i)
|
||||
{
|
||||
return type(i.view);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,590 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2016 Jakub Szuppe <j.szuppe@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
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_MERGE_SORT_ON_GPU_HPP_
|
||||
#define BOOST_COMPUTE_ALGORITHM_DETAIL_MERGE_SORT_ON_GPU_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/compute/kernel.hpp>
|
||||
#include <boost/compute/program.hpp>
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/container/vector.hpp>
|
||||
#include <boost/compute/memory/local_buffer.hpp>
|
||||
#include <boost/compute/detail/meta_kernel.hpp>
|
||||
#include <boost/compute/detail/iterator_range_size.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
namespace detail {
|
||||
|
||||
template<class KeyType, class ValueType>
|
||||
inline size_t pick_bitonic_block_sort_block_size(size_t proposed_wg,
|
||||
size_t lmem_size,
|
||||
bool sort_by_key)
|
||||
{
|
||||
size_t n = proposed_wg;
|
||||
|
||||
size_t lmem_required = n * sizeof(KeyType);
|
||||
if(sort_by_key) {
|
||||
lmem_required += n * sizeof(ValueType);
|
||||
}
|
||||
|
||||
// try to force at least 4 work-groups of >64 elements
|
||||
// for better occupancy
|
||||
while(lmem_size < (lmem_required * 4) && (n > 64)) {
|
||||
n /= 2;
|
||||
lmem_required = n * sizeof(KeyType);
|
||||
}
|
||||
while(lmem_size < lmem_required && (n != 1)) {
|
||||
n /= 2;
|
||||
if(n < 1) n = 1;
|
||||
lmem_required = n * sizeof(KeyType);
|
||||
}
|
||||
|
||||
if(n < 2) { return 1; }
|
||||
else if(n < 4) { return 2; }
|
||||
else if(n < 8) { return 4; }
|
||||
else if(n < 16) { return 8; }
|
||||
else if(n < 32) { return 16; }
|
||||
else if(n < 64) { return 32; }
|
||||
else if(n < 128) { return 64; }
|
||||
else if(n < 256) { return 128; }
|
||||
else { return 256; }
|
||||
}
|
||||
|
||||
|
||||
/// Performs bitonic block sort according to \p compare.
|
||||
///
|
||||
/// Since bitonic sort can be only performed when input size is equal to 2^n,
|
||||
/// in this case input size is block size (\p work_group_size), we would have
|
||||
/// to require \p count be a exact multiple of block size. That would not be
|
||||
/// great.
|
||||
/// Instead, bitonic sort kernel is merged with odd-even merge sort so if the
|
||||
/// last block is not equal to 2^n (where n is some natural number) the odd-even
|
||||
/// sort is performed for that block. That way bitonic_block_sort() works for
|
||||
/// input of any size. Block size (\p work_group_size) still have to be equal
|
||||
/// to 2^n.
|
||||
///
|
||||
/// This is NOT stable.
|
||||
///
|
||||
/// \param keys_first first key element in the range to sort
|
||||
/// \param values_first first value element in the range to sort
|
||||
/// \param compare comparison function for keys
|
||||
/// \param count number of elements in the range; count > 0
|
||||
/// \param work_group_size size of the work group, also the block size; must be
|
||||
/// equal to n^2 where n is natural number
|
||||
/// \param queue command queue to perform the operation
|
||||
template<class KeyIterator, class ValueIterator, class Compare>
|
||||
inline size_t bitonic_block_sort(KeyIterator keys_first,
|
||||
ValueIterator values_first,
|
||||
Compare compare,
|
||||
const size_t count,
|
||||
const bool sort_by_key,
|
||||
command_queue &queue)
|
||||
{
|
||||
typedef typename std::iterator_traits<KeyIterator>::value_type key_type;
|
||||
|
||||
meta_kernel k("bitonic_block_sort");
|
||||
size_t count_arg = k.add_arg<const uint_>("count");
|
||||
|
||||
size_t local_keys_arg = k.add_arg<key_type *>(memory_object::local_memory, "lkeys");
|
||||
size_t local_vals_arg = 0;
|
||||
if(sort_by_key) {
|
||||
local_vals_arg = k.add_arg<uchar_ *>(memory_object::local_memory, "lidx");
|
||||
}
|
||||
|
||||
k <<
|
||||
// Work item global and local ids
|
||||
k.decl<const uint_>("gid") << " = get_global_id(0);\n" <<
|
||||
k.decl<const uint_>("lid") << " = get_local_id(0);\n";
|
||||
|
||||
// declare my_key and my_value
|
||||
k <<
|
||||
k.decl<key_type>("my_key") << ";\n";
|
||||
// Instead of copying values (my_value) in local memory with keys
|
||||
// we save local index (uchar) and copy my_value at the end at
|
||||
// final index. This saves local memory.
|
||||
if(sort_by_key)
|
||||
{
|
||||
k <<
|
||||
k.decl<uchar_>("my_index") << " = (uchar)(lid);\n";
|
||||
}
|
||||
|
||||
// load key
|
||||
k <<
|
||||
"if(gid < count) {\n" <<
|
||||
k.var<key_type>("my_key") << " = " <<
|
||||
keys_first[k.var<const uint_>("gid")] << ";\n" <<
|
||||
"}\n";
|
||||
|
||||
// load key and index to local memory
|
||||
k <<
|
||||
"lkeys[lid] = my_key;\n";
|
||||
if(sort_by_key)
|
||||
{
|
||||
k <<
|
||||
"lidx[lid] = my_index;\n";
|
||||
}
|
||||
k <<
|
||||
k.decl<const uint_>("offset") << " = get_group_id(0) * get_local_size(0);\n" <<
|
||||
k.decl<const uint_>("n") << " = min((uint)(get_local_size(0)),(count - offset));\n";
|
||||
|
||||
// When work group size is a power of 2 bitonic sorter can be used;
|
||||
// otherwise, slower odd-even sort is used.
|
||||
|
||||
k <<
|
||||
// check if n is power of 2
|
||||
"if(((n != 0) && ((n & (~n + 1)) == n))) {\n";
|
||||
|
||||
// bitonic sort, not stable
|
||||
k <<
|
||||
// wait for keys and vals to be stored in local memory
|
||||
"barrier(CLK_LOCAL_MEM_FENCE);\n" <<
|
||||
|
||||
"#pragma unroll\n" <<
|
||||
"for(" <<
|
||||
k.decl<uint_>("length") << " = 1; " <<
|
||||
"length < n; " <<
|
||||
"length <<= 1" <<
|
||||
") {\n" <<
|
||||
// direction of sort: false -> asc, true -> desc
|
||||
k.decl<bool>("direction") << "= ((lid & (length<<1)) != 0);\n" <<
|
||||
"for(" <<
|
||||
k.decl<uint_>("k") << " = length; " <<
|
||||
"k > 0; " <<
|
||||
"k >>= 1" <<
|
||||
") {\n" <<
|
||||
|
||||
// sibling to compare with my key
|
||||
k.decl<uint_>("sibling_idx") << " = lid ^ k;\n" <<
|
||||
k.decl<key_type>("sibling_key") << " = lkeys[sibling_idx];\n" <<
|
||||
k.decl<bool>("compare") << " = " <<
|
||||
compare(k.var<key_type>("sibling_key"),
|
||||
k.var<key_type>("my_key")) << ";\n" <<
|
||||
k.decl<bool>("swap") <<
|
||||
" = compare ^ (sibling_idx < lid) ^ direction;\n" <<
|
||||
"my_key = swap ? sibling_key : my_key;\n";
|
||||
if(sort_by_key)
|
||||
{
|
||||
k <<
|
||||
"my_index = swap ? lidx[sibling_idx] : my_index;\n";
|
||||
}
|
||||
k <<
|
||||
"barrier(CLK_LOCAL_MEM_FENCE);\n" <<
|
||||
"lkeys[lid] = my_key;\n";
|
||||
if(sort_by_key)
|
||||
{
|
||||
k <<
|
||||
"lidx[lid] = my_index;\n";
|
||||
}
|
||||
k <<
|
||||
"barrier(CLK_LOCAL_MEM_FENCE);\n" <<
|
||||
"}\n" <<
|
||||
"}\n";
|
||||
|
||||
// end of bitonic sort
|
||||
|
||||
// odd-even sort, not stable
|
||||
k <<
|
||||
"}\n" <<
|
||||
"else { \n";
|
||||
|
||||
k <<
|
||||
k.decl<bool>("lid_is_even") << " = (lid%2) == 0;\n" <<
|
||||
k.decl<uint_>("oddsibling_idx") << " = " <<
|
||||
"(lid_is_even) ? max(lid,(uint)(1)) - 1 : min(lid+1,n-1);\n" <<
|
||||
k.decl<uint_>("evensibling_idx") << " = " <<
|
||||
"(lid_is_even) ? min(lid+1,n-1) : max(lid,(uint)(1)) - 1;\n" <<
|
||||
|
||||
// wait for keys and vals to be stored in local memory
|
||||
"barrier(CLK_LOCAL_MEM_FENCE);\n" <<
|
||||
|
||||
"#pragma unroll\n" <<
|
||||
"for(" <<
|
||||
k.decl<uint_>("i") << " = 0; " <<
|
||||
"i < n; " <<
|
||||
"i++" <<
|
||||
") {\n" <<
|
||||
k.decl<uint_>("sibling_idx") <<
|
||||
" = i%2 == 0 ? evensibling_idx : oddsibling_idx;\n" <<
|
||||
k.decl<key_type>("sibling_key") << " = lkeys[sibling_idx];\n" <<
|
||||
k.decl<bool>("compare") << " = " <<
|
||||
compare(k.var<key_type>("sibling_key"),
|
||||
k.var<key_type>("my_key")) << ";\n" <<
|
||||
k.decl<bool>("swap") <<
|
||||
" = compare ^ (sibling_idx < lid);\n" <<
|
||||
"my_key = swap ? sibling_key : my_key;\n";
|
||||
if(sort_by_key)
|
||||
{
|
||||
k <<
|
||||
"my_index = swap ? lidx[sibling_idx] : my_index;\n";
|
||||
}
|
||||
k <<
|
||||
"barrier(CLK_LOCAL_MEM_FENCE);\n" <<
|
||||
"lkeys[lid] = my_key;\n";
|
||||
if(sort_by_key)
|
||||
{
|
||||
k <<
|
||||
"lidx[lid] = my_index;\n";
|
||||
}
|
||||
k <<
|
||||
"barrier(CLK_LOCAL_MEM_FENCE);\n"
|
||||
"}\n" << // for
|
||||
|
||||
"}\n"; // else
|
||||
// end of odd-even sort
|
||||
|
||||
// save key and value
|
||||
k <<
|
||||
"if(gid < count) {\n" <<
|
||||
keys_first[k.var<const uint_>("gid")] << " = " <<
|
||||
k.var<key_type>("my_key") << ";\n";
|
||||
if(sort_by_key)
|
||||
{
|
||||
k << values_first[k.var<const uint_>("gid")] << " = " <<
|
||||
values_first[k.var<const uint_>("offset + my_index")] << ";\n";
|
||||
}
|
||||
k <<
|
||||
// end if
|
||||
"}\n";
|
||||
|
||||
const context &context = queue.get_context();
|
||||
const device &device = queue.get_device();
|
||||
::boost::compute::kernel kernel = k.compile(context);
|
||||
|
||||
const size_t work_group_size =
|
||||
pick_bitonic_block_sort_block_size<key_type, uchar_>(
|
||||
kernel.get_work_group_info<size_t>(
|
||||
device, CL_KERNEL_WORK_GROUP_SIZE
|
||||
),
|
||||
device.get_info<size_t>(CL_DEVICE_LOCAL_MEM_SIZE),
|
||||
sort_by_key
|
||||
);
|
||||
|
||||
const size_t global_size =
|
||||
work_group_size * static_cast<size_t>(
|
||||
std::ceil(float(count) / work_group_size)
|
||||
);
|
||||
|
||||
kernel.set_arg(count_arg, static_cast<uint_>(count));
|
||||
kernel.set_arg(local_keys_arg, local_buffer<key_type>(work_group_size));
|
||||
if(sort_by_key) {
|
||||
kernel.set_arg(local_vals_arg, local_buffer<uchar_>(work_group_size));
|
||||
}
|
||||
|
||||
queue.enqueue_1d_range_kernel(kernel, 0, global_size, work_group_size);
|
||||
// return size of the block
|
||||
return work_group_size;
|
||||
}
|
||||
|
||||
template<class KeyIterator, class ValueIterator, class Compare>
|
||||
inline size_t block_sort(KeyIterator keys_first,
|
||||
ValueIterator values_first,
|
||||
Compare compare,
|
||||
const size_t count,
|
||||
const bool sort_by_key,
|
||||
const bool stable,
|
||||
command_queue &queue)
|
||||
{
|
||||
if(stable) {
|
||||
// TODO: Implement stable block sort (stable odd-even merge sort)
|
||||
return size_t(1);
|
||||
}
|
||||
return bitonic_block_sort(
|
||||
keys_first, values_first,
|
||||
compare, count,
|
||||
sort_by_key, queue
|
||||
);
|
||||
}
|
||||
|
||||
/// space: O(n + m); n - number of keys, m - number of values
|
||||
template<class KeyIterator, class ValueIterator, class Compare>
|
||||
inline void merge_blocks_on_gpu(KeyIterator keys_first,
|
||||
ValueIterator values_first,
|
||||
KeyIterator out_keys_first,
|
||||
ValueIterator out_values_first,
|
||||
Compare compare,
|
||||
const size_t count,
|
||||
const size_t block_size,
|
||||
const bool sort_by_key,
|
||||
command_queue &queue)
|
||||
{
|
||||
typedef typename std::iterator_traits<KeyIterator>::value_type key_type;
|
||||
typedef typename std::iterator_traits<ValueIterator>::value_type value_type;
|
||||
|
||||
meta_kernel k("merge_blocks");
|
||||
size_t count_arg = k.add_arg<const uint_>("count");
|
||||
size_t block_size_arg = k.add_arg<const uint_>("block_size");
|
||||
|
||||
k <<
|
||||
// get global id
|
||||
k.decl<const uint_>("gid") << " = get_global_id(0);\n" <<
|
||||
"if(gid >= count) {\n" <<
|
||||
"return;\n" <<
|
||||
"}\n" <<
|
||||
|
||||
k.decl<const key_type>("my_key") << " = " <<
|
||||
keys_first[k.var<const uint_>("gid")] << ";\n";
|
||||
|
||||
if(sort_by_key) {
|
||||
k <<
|
||||
k.decl<const value_type>("my_value") << " = " <<
|
||||
values_first[k.var<const uint_>("gid")] << ";\n";
|
||||
}
|
||||
|
||||
k <<
|
||||
// get my block idx
|
||||
k.decl<const uint_>("my_block_idx") << " = gid / block_size;\n" <<
|
||||
k.decl<const bool>("my_block_idx_is_odd") << " = " <<
|
||||
"my_block_idx & 0x1;\n" <<
|
||||
|
||||
k.decl<const uint_>("other_block_idx") << " = " <<
|
||||
// if(my_block_idx is odd) {} else {}
|
||||
"my_block_idx_is_odd ? my_block_idx - 1 : my_block_idx + 1;\n" <<
|
||||
|
||||
// get ranges of my block and the other block
|
||||
// [my_block_start; my_block_end)
|
||||
// [other_block_start; other_block_end)
|
||||
k.decl<const uint_>("my_block_start") << " = " <<
|
||||
"min(my_block_idx * block_size, count);\n" << // including
|
||||
k.decl<const uint_>("my_block_end") << " = " <<
|
||||
"min((my_block_idx + 1) * block_size, count);\n" << // excluding
|
||||
|
||||
k.decl<const uint_>("other_block_start") << " = " <<
|
||||
"min(other_block_idx * block_size, count);\n" << // including
|
||||
k.decl<const uint_>("other_block_end") << " = " <<
|
||||
"min((other_block_idx + 1) * block_size, count);\n" << // excluding
|
||||
|
||||
// other block is empty, nothing to merge here
|
||||
"if(other_block_start == count){\n" <<
|
||||
out_keys_first[k.var<uint_>("gid")] << " = my_key;\n";
|
||||
if(sort_by_key) {
|
||||
k <<
|
||||
out_values_first[k.var<uint_>("gid")] << " = my_value;\n";
|
||||
}
|
||||
|
||||
k <<
|
||||
"return;\n" <<
|
||||
"}\n" <<
|
||||
|
||||
// lower bound
|
||||
// left_idx - lower bound
|
||||
k.decl<uint_>("left_idx") << " = other_block_start;\n" <<
|
||||
k.decl<uint_>("right_idx") << " = other_block_end;\n" <<
|
||||
"while(left_idx < right_idx) {\n" <<
|
||||
k.decl<uint_>("mid_idx") << " = (left_idx + right_idx) / 2;\n" <<
|
||||
k.decl<key_type>("mid_key") << " = " <<
|
||||
keys_first[k.var<const uint_>("mid_idx")] << ";\n" <<
|
||||
k.decl<bool>("smaller") << " = " <<
|
||||
compare(k.var<key_type>("mid_key"),
|
||||
k.var<key_type>("my_key")) << ";\n" <<
|
||||
"left_idx = smaller ? mid_idx + 1 : left_idx;\n" <<
|
||||
"right_idx = smaller ? right_idx : mid_idx;\n" <<
|
||||
"}\n" <<
|
||||
// left_idx is found position in other block
|
||||
|
||||
// if my_block is odd we need to get the upper bound
|
||||
"right_idx = other_block_end;\n" <<
|
||||
"if(my_block_idx_is_odd && left_idx != right_idx) {\n" <<
|
||||
k.decl<key_type>("upper_key") << " = " <<
|
||||
keys_first[k.var<const uint_>("left_idx")] << ";\n" <<
|
||||
"while(" <<
|
||||
"!(" << compare(k.var<key_type>("upper_key"),
|
||||
k.var<key_type>("my_key")) <<
|
||||
") && " <<
|
||||
"!(" << compare(k.var<key_type>("my_key"),
|
||||
k.var<key_type>("upper_key")) <<
|
||||
") && " <<
|
||||
"left_idx < right_idx" <<
|
||||
")" <<
|
||||
"{\n" <<
|
||||
k.decl<uint_>("mid_idx") << " = (left_idx + right_idx) / 2;\n" <<
|
||||
k.decl<key_type>("mid_key") << " = " <<
|
||||
keys_first[k.var<const uint_>("mid_idx")] << ";\n" <<
|
||||
k.decl<bool>("equal") << " = " <<
|
||||
"!(" << compare(k.var<key_type>("mid_key"),
|
||||
k.var<key_type>("my_key")) <<
|
||||
") && " <<
|
||||
"!(" << compare(k.var<key_type>("my_key"),
|
||||
k.var<key_type>("mid_key")) <<
|
||||
");\n" <<
|
||||
"left_idx = equal ? mid_idx + 1 : left_idx + 1;\n" <<
|
||||
"right_idx = equal ? right_idx : mid_idx;\n" <<
|
||||
"upper_key = equal ? upper_key : " <<
|
||||
keys_first[k.var<const uint_>("left_idx")] << ";\n" <<
|
||||
"}\n" <<
|
||||
"}\n" <<
|
||||
|
||||
k.decl<uint_>("offset") << " = 0;\n" <<
|
||||
"offset += gid - my_block_start;\n" <<
|
||||
"offset += left_idx - other_block_start;\n" <<
|
||||
"offset += min(my_block_start, other_block_start);\n" <<
|
||||
out_keys_first[k.var<uint_>("offset")] << " = my_key;\n";
|
||||
if(sort_by_key) {
|
||||
k <<
|
||||
out_values_first[k.var<uint_>("offset")] << " = my_value;\n";
|
||||
}
|
||||
|
||||
const context &context = queue.get_context();
|
||||
::boost::compute::kernel kernel = k.compile(context);
|
||||
|
||||
const size_t work_group_size = (std::min)(
|
||||
size_t(256),
|
||||
kernel.get_work_group_info<size_t>(
|
||||
queue.get_device(), CL_KERNEL_WORK_GROUP_SIZE
|
||||
)
|
||||
);
|
||||
const size_t global_size =
|
||||
work_group_size * static_cast<size_t>(
|
||||
std::ceil(float(count) / work_group_size)
|
||||
);
|
||||
|
||||
kernel.set_arg(count_arg, static_cast<uint_>(count));
|
||||
kernel.set_arg(block_size_arg, static_cast<uint_>(block_size));
|
||||
queue.enqueue_1d_range_kernel(kernel, 0, global_size, work_group_size);
|
||||
}
|
||||
|
||||
template<class KeyIterator, class ValueIterator, class Compare>
|
||||
inline void merge_sort_by_key_on_gpu(KeyIterator keys_first,
|
||||
KeyIterator keys_last,
|
||||
ValueIterator values_first,
|
||||
Compare compare,
|
||||
bool stable,
|
||||
command_queue &queue)
|
||||
{
|
||||
typedef typename std::iterator_traits<KeyIterator>::value_type key_type;
|
||||
typedef typename std::iterator_traits<ValueIterator>::value_type value_type;
|
||||
|
||||
size_t count = iterator_range_size(keys_first, keys_last);
|
||||
if(count < 2){
|
||||
return;
|
||||
}
|
||||
|
||||
size_t block_size =
|
||||
block_sort(
|
||||
keys_first, values_first,
|
||||
compare, count,
|
||||
true /* sort_by_key */, stable /* stable */,
|
||||
queue
|
||||
);
|
||||
|
||||
// for small input size only block sort is performed
|
||||
if(count <= block_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
const context &context = queue.get_context();
|
||||
|
||||
bool result_in_temporary_buffer = false;
|
||||
::boost::compute::vector<key_type> temp_keys(count, context);
|
||||
::boost::compute::vector<value_type> temp_values(count, context);
|
||||
|
||||
for(; block_size < count; block_size *= 2) {
|
||||
result_in_temporary_buffer = !result_in_temporary_buffer;
|
||||
if(result_in_temporary_buffer) {
|
||||
merge_blocks_on_gpu(keys_first, values_first,
|
||||
temp_keys.begin(), temp_values.begin(),
|
||||
compare, count, block_size,
|
||||
true /* sort_by_key */, queue);
|
||||
} else {
|
||||
merge_blocks_on_gpu(temp_keys.begin(), temp_values.begin(),
|
||||
keys_first, values_first,
|
||||
compare, count, block_size,
|
||||
true /* sort_by_key */, queue);
|
||||
}
|
||||
}
|
||||
|
||||
if(result_in_temporary_buffer) {
|
||||
copy_async(temp_keys.begin(), temp_keys.end(), keys_first, queue);
|
||||
copy_async(temp_values.begin(), temp_values.end(), values_first, queue);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Iterator, class Compare>
|
||||
inline void merge_sort_on_gpu(Iterator first,
|
||||
Iterator last,
|
||||
Compare compare,
|
||||
bool stable,
|
||||
command_queue &queue)
|
||||
{
|
||||
typedef typename std::iterator_traits<Iterator>::value_type key_type;
|
||||
|
||||
size_t count = iterator_range_size(first, last);
|
||||
if(count < 2){
|
||||
return;
|
||||
}
|
||||
|
||||
Iterator dummy;
|
||||
size_t block_size =
|
||||
block_sort(
|
||||
first, dummy,
|
||||
compare, count,
|
||||
false /* sort_by_key */, stable /* stable */,
|
||||
queue
|
||||
);
|
||||
|
||||
// for small input size only block sort is performed
|
||||
if(count <= block_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
const context &context = queue.get_context();
|
||||
|
||||
bool result_in_temporary_buffer = false;
|
||||
::boost::compute::vector<key_type> temp_keys(count, context);
|
||||
|
||||
for(; block_size < count; block_size *= 2) {
|
||||
result_in_temporary_buffer = !result_in_temporary_buffer;
|
||||
if(result_in_temporary_buffer) {
|
||||
merge_blocks_on_gpu(first, dummy, temp_keys.begin(), dummy,
|
||||
compare, count, block_size,
|
||||
false /* sort_by_key */, queue);
|
||||
} else {
|
||||
merge_blocks_on_gpu(temp_keys.begin(), dummy, first, dummy,
|
||||
compare, count, block_size,
|
||||
false /* sort_by_key */, queue);
|
||||
}
|
||||
}
|
||||
|
||||
if(result_in_temporary_buffer) {
|
||||
copy_async(temp_keys.begin(), temp_keys.end(), first, queue);
|
||||
}
|
||||
}
|
||||
|
||||
template<class KeyIterator, class ValueIterator, class Compare>
|
||||
inline void merge_sort_by_key_on_gpu(KeyIterator keys_first,
|
||||
KeyIterator keys_last,
|
||||
ValueIterator values_first,
|
||||
Compare compare,
|
||||
command_queue &queue)
|
||||
{
|
||||
merge_sort_by_key_on_gpu(
|
||||
keys_first, keys_last, values_first,
|
||||
compare, false /* not stable */, queue
|
||||
);
|
||||
}
|
||||
|
||||
template<class Iterator, class Compare>
|
||||
inline void merge_sort_on_gpu(Iterator first,
|
||||
Iterator last,
|
||||
Compare compare,
|
||||
command_queue &queue)
|
||||
{
|
||||
merge_sort_on_gpu(
|
||||
first, last, compare, false /* not stable */, queue
|
||||
);
|
||||
}
|
||||
|
||||
} // end detail namespace
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif /* BOOST_COMPUTE_ALGORITHM_DETAIL_MERGE_SORT_ON_GPU_HPP_ */
|
||||
@@ -0,0 +1,79 @@
|
||||
#if !defined(BOOST_PROTO_DONT_USE_PREPROCESSED_FILES)
|
||||
|
||||
#include <boost/proto/detail/preprocessed/deep_copy.hpp>
|
||||
|
||||
#elif !defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
#define BOOST_PROTO_DEFINE_DEEP_COPY_TYPE(Z, N, DATA) \
|
||||
typename deep_copy_impl< \
|
||||
typename remove_reference< \
|
||||
typename Expr::BOOST_PP_CAT(proto_child, N) \
|
||||
>::type::proto_derived_expr \
|
||||
>::result_type \
|
||||
/**/
|
||||
|
||||
#define BOOST_PROTO_DEFINE_DEEP_COPY_FUN(Z, N, DATA) \
|
||||
proto::deep_copy(e.proto_base().BOOST_PP_CAT(child, N)) \
|
||||
/**/
|
||||
|
||||
#if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES)
|
||||
#pragma wave option(preserve: 2, line: 0, output: "preprocessed/deep_copy.hpp")
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// \file deep_copy.hpp
|
||||
/// Replace all nodes stored by reference by nodes stored by value.
|
||||
//
|
||||
// Copyright 2008 Eric Niebler. Distributed under the 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_PROTO_CREATE_PREPROCESSED_FILES)
|
||||
#pragma wave option(preserve: 1)
|
||||
#endif
|
||||
|
||||
#define BOOST_PP_ITERATION_PARAMS_1 \
|
||||
(3, (1, BOOST_PROTO_MAX_ARITY, <boost/proto/detail/deep_copy.hpp>))
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
#if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES)
|
||||
#pragma wave option(output: null)
|
||||
#endif
|
||||
|
||||
#undef BOOST_PROTO_DEFINE_DEEP_COPY_FUN
|
||||
#undef BOOST_PROTO_DEFINE_DEEP_COPY_TYPE
|
||||
|
||||
#else
|
||||
|
||||
#define N BOOST_PP_ITERATION()
|
||||
|
||||
template<typename Expr>
|
||||
struct deep_copy_impl<Expr, N>
|
||||
{
|
||||
typedef
|
||||
typename base_expr<
|
||||
typename Expr::proto_domain
|
||||
, typename Expr::proto_tag
|
||||
, BOOST_PP_CAT(list, N)<
|
||||
BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_DEEP_COPY_TYPE, ~)
|
||||
>
|
||||
>::type
|
||||
expr_type;
|
||||
|
||||
typedef typename Expr::proto_generator proto_generator;
|
||||
typedef typename proto_generator::template result<proto_generator(expr_type)>::type result_type;
|
||||
|
||||
template<typename Expr2, typename S, typename D>
|
||||
result_type operator()(Expr2 const &e, S const &, D const &) const
|
||||
{
|
||||
expr_type const that = {
|
||||
BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_DEEP_COPY_FUN, ~)
|
||||
};
|
||||
|
||||
return proto_generator()(that);
|
||||
}
|
||||
};
|
||||
|
||||
#undef N
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
// Boost.Units - A C++ library for zero-overhead dimensional analysis and
|
||||
// unit/quantity manipulation and conversion
|
||||
//
|
||||
// Copyright (C) 2003-2008 Matthias Christian Schabel
|
||||
// Copyright (C) 2007-2008 Steven Watanabe
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_UNITS_SI_CANDELA_BASE_UNIT_HPP
|
||||
#define BOOST_UNITS_SI_CANDELA_BASE_UNIT_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/units/config.hpp>
|
||||
#include <boost/units/base_unit.hpp>
|
||||
#include <boost/units/physical_dimensions/luminous_intensity.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace units {
|
||||
|
||||
namespace si {
|
||||
|
||||
struct candela_base_unit : public base_unit<candela_base_unit, luminous_intensity_dimension, -3>
|
||||
{
|
||||
static std::string name() { return("candela"); }
|
||||
static std::string symbol() { return("cd"); }
|
||||
};
|
||||
|
||||
} // namespace si
|
||||
|
||||
} // namespace units
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#if BOOST_UNITS_HAS_BOOST_TYPEOF
|
||||
|
||||
#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
|
||||
|
||||
BOOST_TYPEOF_REGISTER_TYPE(boost::units::si::candela_base_unit)
|
||||
|
||||
#endif
|
||||
|
||||
//#include <boost/units/base_units/detail/conversions.hpp>
|
||||
|
||||
#endif // BOOST_UNITS_SI_CANDELA_BASE_UNIT_HPP
|
||||
@@ -0,0 +1,121 @@
|
||||
// posix/chrono.cpp --------------------------------------------------------------//
|
||||
|
||||
// Copyright Beman Dawes 2008
|
||||
// Copyright Vicente J. Botet Escriba 2009
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// POSIX //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#include <time.h> // for clock_gettime
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace chrono
|
||||
{
|
||||
|
||||
system_clock::time_point system_clock::now() BOOST_NOEXCEPT
|
||||
{
|
||||
timespec ts;
|
||||
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
|
||||
{
|
||||
BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
|
||||
}
|
||||
|
||||
return time_point(duration(
|
||||
static_cast<system_clock::rep>( ts.tv_sec ) * 1000000000 + ts.tv_nsec));
|
||||
}
|
||||
|
||||
#if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
|
||||
system_clock::time_point system_clock::now(system::error_code & ec)
|
||||
{
|
||||
timespec ts;
|
||||
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
|
||||
{
|
||||
if (BOOST_CHRONO_IS_THROWS(ec))
|
||||
{
|
||||
boost::throw_exception(
|
||||
system::system_error(
|
||||
errno,
|
||||
BOOST_CHRONO_SYSTEM_CATEGORY,
|
||||
"chrono::system_clock" ));
|
||||
}
|
||||
else
|
||||
{
|
||||
ec.assign( errno, BOOST_CHRONO_SYSTEM_CATEGORY );
|
||||
return time_point();
|
||||
}
|
||||
}
|
||||
|
||||
if (!BOOST_CHRONO_IS_THROWS(ec))
|
||||
{
|
||||
ec.clear();
|
||||
}
|
||||
return time_point(duration(
|
||||
static_cast<system_clock::rep>( ts.tv_sec ) * 1000000000 + ts.tv_nsec));
|
||||
}
|
||||
#endif
|
||||
|
||||
std::time_t system_clock::to_time_t(const system_clock::time_point& t) BOOST_NOEXCEPT
|
||||
{
|
||||
return static_cast<std::time_t>( t.time_since_epoch().count() / 1000000000 );
|
||||
}
|
||||
|
||||
system_clock::time_point system_clock::from_time_t(std::time_t t) BOOST_NOEXCEPT
|
||||
{
|
||||
return time_point(duration(static_cast<system_clock::rep>(t) * 1000000000));
|
||||
}
|
||||
|
||||
#ifdef BOOST_CHRONO_HAS_CLOCK_STEADY
|
||||
|
||||
steady_clock::time_point steady_clock::now() BOOST_NOEXCEPT
|
||||
{
|
||||
timespec ts;
|
||||
if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
|
||||
{
|
||||
BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
|
||||
}
|
||||
|
||||
return time_point(duration(
|
||||
static_cast<steady_clock::rep>( ts.tv_sec ) * 1000000000 + ts.tv_nsec));
|
||||
}
|
||||
|
||||
#if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
|
||||
steady_clock::time_point steady_clock::now(system::error_code & ec)
|
||||
{
|
||||
timespec ts;
|
||||
if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
|
||||
{
|
||||
if (BOOST_CHRONO_IS_THROWS(ec))
|
||||
{
|
||||
boost::throw_exception(
|
||||
system::system_error(
|
||||
errno,
|
||||
BOOST_CHRONO_SYSTEM_CATEGORY,
|
||||
"chrono::steady_clock" ));
|
||||
}
|
||||
else
|
||||
{
|
||||
ec.assign( errno, BOOST_CHRONO_SYSTEM_CATEGORY );
|
||||
return time_point();
|
||||
}
|
||||
}
|
||||
|
||||
if (!BOOST_CHRONO_IS_THROWS(ec))
|
||||
{
|
||||
ec.clear();
|
||||
}
|
||||
return time_point(duration(
|
||||
static_cast<steady_clock::rep>( ts.tv_sec ) * 1000000000 + ts.tv_nsec));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} // namespace chrono
|
||||
} // namespace boost
|
||||
|
||||
|
||||
@@ -0,0 +1,429 @@
|
||||
subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
|
||||
!$ use omp_lib
|
||||
use prog_args
|
||||
use timer_module, only: timer
|
||||
use jt4_decode
|
||||
use jt65_decode
|
||||
use jt9_decode
|
||||
use ft8_decode
|
||||
|
||||
include 'jt9com.f90'
|
||||
include 'timer_common.inc'
|
||||
|
||||
type, extends(jt4_decoder) :: counting_jt4_decoder
|
||||
integer :: decoded
|
||||
end type counting_jt4_decoder
|
||||
|
||||
type, extends(jt65_decoder) :: counting_jt65_decoder
|
||||
integer :: decoded
|
||||
end type counting_jt65_decoder
|
||||
|
||||
type, extends(jt9_decoder) :: counting_jt9_decoder
|
||||
integer :: decoded
|
||||
end type counting_jt9_decoder
|
||||
|
||||
type, extends(ft8_decoder) :: counting_ft8_decoder
|
||||
integer :: decoded
|
||||
end type counting_ft8_decoder
|
||||
|
||||
real ss(184,NSMAX)
|
||||
logical baddata,newdat65,newdat9,single_decode,bVHF,bad0,newdat
|
||||
integer*2 id2(NTMAX*12000)
|
||||
type(params_block) :: params
|
||||
real*4 dd(NTMAX*12000)
|
||||
save
|
||||
type(counting_jt4_decoder) :: my_jt4
|
||||
type(counting_jt65_decoder) :: my_jt65
|
||||
type(counting_jt9_decoder) :: my_jt9
|
||||
type(counting_ft8_decoder) :: my_ft8
|
||||
|
||||
! initialize decode counts
|
||||
my_jt4%decoded = 0
|
||||
my_jt65%decoded = 0
|
||||
my_jt9%decoded = 0
|
||||
my_ft8%decoded = 0
|
||||
|
||||
single_decode=iand(params%nexp_decode,32).ne.0
|
||||
bVHF=iand(params%nexp_decode,64).ne.0
|
||||
if(mod(params%nranera,2).eq.0) ntrials=10**(params%nranera/2)
|
||||
if(mod(params%nranera,2).eq.1) ntrials=3*10**(params%nranera/2)
|
||||
if(params%nranera.eq.0) ntrials=0
|
||||
|
||||
nfail=0
|
||||
10 if (params%nagain) then
|
||||
open(13,file=trim(temp_dir)//'/decoded.txt',status='unknown', &
|
||||
position='append',iostat=ios)
|
||||
else
|
||||
open(13,file=trim(temp_dir)//'/decoded.txt',status='unknown', &
|
||||
iostat=ios)
|
||||
end if
|
||||
if(ios.ne.0) then
|
||||
nfail=nfail+1
|
||||
if(nfail.le.3) then
|
||||
call sleep_msec(10)
|
||||
go to 10
|
||||
endif
|
||||
endif
|
||||
|
||||
if(params%nmode.eq.8) then
|
||||
! We're in FT8 mode
|
||||
call timer('decft8 ',0)
|
||||
newdat=params%newdat
|
||||
call my_ft8%decode(ft8_decoded,id2,params%nQSOProgress,params%nfqso, &
|
||||
params%nftx,newdat,params%nutc,params%nfa, &
|
||||
params%nfb,logical(params%nagain), &
|
||||
params%ndepth,logical(params%lapon),params%napwid,params%nsubmode, &
|
||||
params%mycall,params%hiscall,params%hisgrid)
|
||||
call timer('decft8 ',1)
|
||||
go to 800
|
||||
endif
|
||||
|
||||
rms=sqrt(dot_product(float(id2(300000:310000)), &
|
||||
float(id2(300000:310000)))/10000.0)
|
||||
if(rms.lt.2.0) go to 800
|
||||
|
||||
! Zap data at start that might come from T/R switching transient?
|
||||
nadd=100
|
||||
k=0
|
||||
bad0=.false.
|
||||
do i=1,240
|
||||
sq=0.
|
||||
do n=1,nadd
|
||||
k=k+1
|
||||
sq=sq + float(id2(k))**2
|
||||
enddo
|
||||
rms=sqrt(sq/nadd)
|
||||
if(rms.gt.10000.0) then
|
||||
bad0=.true.
|
||||
kbad=k
|
||||
rmsbad=rms
|
||||
endif
|
||||
enddo
|
||||
if(bad0) then
|
||||
nz=min(NTMAX*12000,kbad+100)
|
||||
! id2(1:nz)=0 ! temporarily disabled as it can breaak the JT9 decoder, maybe others
|
||||
endif
|
||||
|
||||
if(params%nmode.eq.4 .or. params%nmode.eq.65) open(14,file=trim(temp_dir)// &
|
||||
'/avemsg.txt',status='unknown')
|
||||
if(params%nmode.eq.164) open(17,file=trim(temp_dir)//'/red.dat', &
|
||||
status='unknown')
|
||||
|
||||
if(params%nmode.eq.4) then
|
||||
jz=52*nfsample
|
||||
if(params%newdat) then
|
||||
if(nfsample.eq.12000) call wav11(id2,jz,dd)
|
||||
if(nfsample.eq.11025) dd(1:jz)=id2(1:jz)
|
||||
endif
|
||||
call my_jt4%decode(jt4_decoded,dd,jz,params%nutc,params%nfqso, &
|
||||
params%ntol,params%emedelay,params%dttol,logical(params%nagain), &
|
||||
params%ndepth,logical(params%nclearave),params%minsync, &
|
||||
params%minw,params%nsubmode,params%mycall,params%hiscall, &
|
||||
params%hisgrid,params%nlist,params%listutc,jt4_average)
|
||||
go to 800
|
||||
endif
|
||||
|
||||
npts65=52*12000
|
||||
if(params%nmode.eq.164) npts65=54*12000
|
||||
if(baddata(id2,npts65)) then
|
||||
nsynced=0
|
||||
ndecoded=0
|
||||
go to 800
|
||||
endif
|
||||
|
||||
ntol65=params%ntol !### is this OK? ###
|
||||
newdat65=params%newdat
|
||||
newdat9=params%newdat
|
||||
|
||||
!$call omp_set_dynamic(.true.)
|
||||
!$omp parallel sections num_threads(2) copyin(/timer_private/) shared(ndecoded) if(.true.) !iif() needed on Mac
|
||||
|
||||
!$omp section
|
||||
if(params%nmode.eq.65 .or. params%nmode.eq.164 .or. &
|
||||
(params%nmode.eq.(65+9) .and. params%ntxmode.eq.65)) then
|
||||
! We're in JT65 or QRA64 mode, or should do JT65 first
|
||||
|
||||
if(newdat65) dd(1:npts65)=id2(1:npts65)
|
||||
nf1=params%nfa
|
||||
nf2=params%nfb
|
||||
call timer('jt65a ',0)
|
||||
call my_jt65%decode(jt65_decoded,dd,npts65,newdat65,params%nutc, &
|
||||
nf1,nf2,params%nfqso,ntol65,params%nsubmode,params%minsync, &
|
||||
logical(params%nagain),params%n2pass,logical(params%nrobust), &
|
||||
ntrials,params%naggressive,params%ndepth,params%emedelay, &
|
||||
logical(params%nclearave),params%mycall,params%hiscall, &
|
||||
params%hisgrid,params%nexp_decode)
|
||||
call timer('jt65a ',1)
|
||||
|
||||
else if(params%nmode.eq.9 .or. (params%nmode.eq.(65+9) .and. params%ntxmode.eq.9)) then
|
||||
! We're in JT9 mode, or should do JT9 first
|
||||
call timer('decjt9 ',0)
|
||||
call my_jt9%decode(jt9_decoded,ss,id2,params%nfqso, &
|
||||
newdat9,params%npts8,params%nfa,params%nfsplit,params%nfb, &
|
||||
params%ntol,params%nzhsym,logical(params%nagain),params%ndepth, &
|
||||
params%nmode,params%nsubmode,params%nexp_decode)
|
||||
call timer('decjt9 ',1)
|
||||
endif
|
||||
|
||||
!$omp section
|
||||
if(params%nmode.eq.(65+9)) then !Do the other mode (we're in dual mode)
|
||||
if (params%ntxmode.eq.9) then
|
||||
if(newdat65) dd(1:npts65)=id2(1:npts65)
|
||||
nf1=params%nfa
|
||||
nf2=params%nfb
|
||||
call timer('jt65a ',0)
|
||||
call my_jt65%decode(jt65_decoded,dd,npts65,newdat65,params%nutc, &
|
||||
nf1,nf2,params%nfqso,ntol65,params%nsubmode,params%minsync, &
|
||||
logical(params%nagain),params%n2pass,logical(params%nrobust), &
|
||||
ntrials,params%naggressive,params%ndepth,params%emedelay, &
|
||||
logical(params%nclearave),params%mycall,params%hiscall, &
|
||||
params%hisgrid,params%nexp_decode)
|
||||
call timer('jt65a ',1)
|
||||
else
|
||||
call timer('decjt9 ',0)
|
||||
call my_jt9%decode(jt9_decoded,ss,id2,params%nfqso, &
|
||||
newdat9,params%npts8,params%nfa,params%nfsplit,params%nfb, &
|
||||
params%ntol,params%nzhsym,logical(params%nagain), &
|
||||
params%ndepth,params%nmode,params%nsubmode,params%nexp_decode)
|
||||
call timer('decjt9 ',1)
|
||||
end if
|
||||
endif
|
||||
|
||||
!$omp end parallel sections
|
||||
|
||||
! JT65 is not yet producing info for nsynced, ndecoded.
|
||||
800 ndecoded = my_jt4%decoded + my_jt65%decoded + my_jt9%decoded + my_ft8%decoded
|
||||
write(*,1010) nsynced,ndecoded
|
||||
1010 format('<DecodeFinished>',2i4)
|
||||
call flush(6)
|
||||
close(13)
|
||||
if(params%nmode.eq.4 .or. params%nmode.eq.65) close(14)
|
||||
|
||||
return
|
||||
|
||||
contains
|
||||
|
||||
subroutine jt4_decoded(this,snr,dt,freq,have_sync,sync,is_deep, &
|
||||
decoded0,qual,ich,is_average,ave)
|
||||
implicit none
|
||||
class(jt4_decoder), intent(inout) :: this
|
||||
integer, intent(in) :: snr
|
||||
real, intent(in) :: dt
|
||||
integer, intent(in) :: freq
|
||||
logical, intent(in) :: have_sync
|
||||
logical, intent(in) :: is_deep
|
||||
character(len=1), intent(in) :: sync
|
||||
character(len=22), intent(in) :: decoded0
|
||||
real, intent(in) :: qual
|
||||
integer, intent(in) :: ich
|
||||
logical, intent(in) :: is_average
|
||||
integer, intent(in) :: ave
|
||||
|
||||
character*22 decoded
|
||||
character*3 cflags
|
||||
|
||||
if(ich.eq.-99) stop !Silence compiler warning
|
||||
if (have_sync) then
|
||||
decoded=decoded0
|
||||
cflags=' '
|
||||
if(decoded.ne.' ') cflags='f '
|
||||
if(is_deep) then
|
||||
cflags(1:2)='d1'
|
||||
write(cflags(3:3),'(i1)') min(int(qual),9)
|
||||
if(qual.ge.10.0) cflags(3:3)='*'
|
||||
if(qual.lt.3.0) decoded(22:22)='?'
|
||||
endif
|
||||
if(is_average) then
|
||||
write(cflags(2:2),'(i1)') min(ave,9)
|
||||
if(ave.ge.10) cflags(2:2)='*'
|
||||
endif
|
||||
write(*,1000) params%nutc,snr,dt,freq,sync,decoded,cflags
|
||||
1000 format(i4.4,i4,f5.1,i5,1x,'$',a1,1x,a22,1x,a3)
|
||||
else
|
||||
write(*,1000) params%nutc,snr,dt,freq
|
||||
end if
|
||||
|
||||
select type(this)
|
||||
type is (counting_jt4_decoder)
|
||||
this%decoded = this%decoded + 1
|
||||
end select
|
||||
end subroutine jt4_decoded
|
||||
|
||||
subroutine jt4_average (this, used, utc, sync, dt, freq, flip)
|
||||
implicit none
|
||||
class(jt4_decoder), intent(inout) :: this
|
||||
logical, intent(in) :: used
|
||||
integer, intent(in) :: utc
|
||||
real, intent(in) :: sync
|
||||
real, intent(in) :: dt
|
||||
integer, intent(in) :: freq
|
||||
logical, intent(in) :: flip
|
||||
character(len=1) :: cused, csync
|
||||
|
||||
cused = '.'
|
||||
csync = '*'
|
||||
if (used) cused = '$'
|
||||
if (flip) csync = '$'
|
||||
write(14,1000) cused,utc,sync,dt,freq,csync
|
||||
1000 format(a1,i5.4,f6.1,f6.2,i6,1x,a1)
|
||||
end subroutine jt4_average
|
||||
|
||||
subroutine jt65_decoded(this,sync,snr,dt,freq,drift,nflip,width, &
|
||||
decoded0,ft,qual,nsmo,nsum,minsync)
|
||||
|
||||
use jt65_decode
|
||||
implicit none
|
||||
|
||||
class(jt65_decoder), intent(inout) :: this
|
||||
real, intent(in) :: sync
|
||||
integer, intent(in) :: snr
|
||||
real, intent(in) :: dt
|
||||
integer, intent(in) :: freq
|
||||
integer, intent(in) :: drift
|
||||
integer, intent(in) :: nflip
|
||||
real, intent(in) :: width
|
||||
character(len=22), intent(in) :: decoded0
|
||||
integer, intent(in) :: ft
|
||||
integer, intent(in) :: qual
|
||||
integer, intent(in) :: nsmo
|
||||
integer, intent(in) :: nsum
|
||||
integer, intent(in) :: minsync
|
||||
|
||||
integer i,nft
|
||||
logical is_deep,is_average
|
||||
character decoded*22,csync*2,cflags*3
|
||||
|
||||
if(width.eq.-9999.0) stop !Silence compiler warning
|
||||
!$omp critical(decode_results)
|
||||
decoded=decoded0
|
||||
cflags=' '
|
||||
is_deep=ft.eq.2
|
||||
|
||||
if(ft.ge.80) then !QRA64 mode
|
||||
nft=ft-100
|
||||
csync=': '
|
||||
if(sync-3.4.ge.float(minsync) .or. nft.ge.0) csync=':*'
|
||||
if(nft.lt.0) then
|
||||
write(*,1009) params%nutc,snr,dt,freq,csync,decoded
|
||||
else
|
||||
write(*,1009) params%nutc,snr,dt,freq,csync,decoded,nft
|
||||
1009 format(i4.4,i4,f5.1,i5,1x,a2,1x,a22,i2)
|
||||
endif
|
||||
write(13,1011) params%nutc,nint(sync),snr,dt,float(freq),drift, &
|
||||
decoded,nft
|
||||
1011 format(i4.4,i4,i5,f6.2,f8.0,i4,3x,a22,' QRA64',i3)
|
||||
go to 100
|
||||
endif
|
||||
|
||||
if(ft.eq.0 .and. minsync.ge.0 .and. int(sync).lt.minsync) then
|
||||
write(*,1010) params%nutc,snr,dt,freq
|
||||
else
|
||||
is_average=nsum.ge.2
|
||||
if(bVHF .and. ft.gt.0) then
|
||||
cflags='f '
|
||||
if(is_deep) then
|
||||
cflags(1:2)='d1'
|
||||
write(cflags(3:3),'(i1)') min(qual,9)
|
||||
if(qual.ge.10) cflags(3:3)='*'
|
||||
if(qual.lt.3) decoded(22:22)='?'
|
||||
endif
|
||||
if(is_average) then
|
||||
write(cflags(2:2),'(i1)') min(nsum,9)
|
||||
if(nsum.ge.10) cflags(2:2)='*'
|
||||
endif
|
||||
endif
|
||||
csync='# '
|
||||
i=0
|
||||
if(bVHF .and. nflip.ne.0 .and. &
|
||||
sync.ge.max(0.0,float(minsync))) then
|
||||
csync='#*'
|
||||
if(nflip.eq.-1) then
|
||||
csync='##'
|
||||
if(decoded.ne.' ') then
|
||||
do i=22,1,-1
|
||||
if(decoded(i:i).ne.' ') exit
|
||||
enddo
|
||||
if(i.gt.18) i=18
|
||||
decoded(i+2:i+4)='OOO'
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
write(*,1010) params%nutc,snr,dt,freq,csync,decoded,cflags
|
||||
1010 format(i4.4,i4,f5.1,i5,1x,a2,1x,a22,1x,a3)
|
||||
endif
|
||||
write(13,1012) params%nutc,nint(sync),snr,dt,float(freq),drift, &
|
||||
decoded,ft,nsum,nsmo
|
||||
1012 format(i4.4,i4,i5,f6.2,f8.0,i4,3x,a22,' JT65',3i3)
|
||||
|
||||
100 call flush(6)
|
||||
|
||||
!$omp end critical(decode_results)
|
||||
select type(this)
|
||||
type is (counting_jt65_decoder)
|
||||
this%decoded = this%decoded + 1
|
||||
end select
|
||||
end subroutine jt65_decoded
|
||||
|
||||
subroutine jt9_decoded (this, sync, snr, dt, freq, drift, decoded)
|
||||
use jt9_decode
|
||||
implicit none
|
||||
|
||||
class(jt9_decoder), intent(inout) :: this
|
||||
real, intent(in) :: sync
|
||||
integer, intent(in) :: snr
|
||||
real, intent(in) :: dt
|
||||
real, intent(in) :: freq
|
||||
integer, intent(in) :: drift
|
||||
character(len=22), intent(in) :: decoded
|
||||
|
||||
!$omp critical(decode_results)
|
||||
write(*,1000) params%nutc,snr,dt,nint(freq),decoded
|
||||
1000 format(i4.4,i4,f5.1,i5,1x,'@ ',1x,a22)
|
||||
write(13,1002) params%nutc,nint(sync),snr,dt,freq,drift,decoded
|
||||
1002 format(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22,' JT9')
|
||||
call flush(6)
|
||||
!$omp end critical(decode_results)
|
||||
select type(this)
|
||||
type is (counting_jt9_decoder)
|
||||
this%decoded = this%decoded + 1
|
||||
end select
|
||||
end subroutine jt9_decoded
|
||||
|
||||
subroutine ft8_decoded (this,sync,snr,dt,freq,decoded,nap,qual)
|
||||
use ft8_decode
|
||||
implicit none
|
||||
|
||||
class(ft8_decoder), intent(inout) :: this
|
||||
real, intent(in) :: sync
|
||||
integer, intent(in) :: snr
|
||||
real, intent(in) :: dt
|
||||
real, intent(in) :: freq
|
||||
character(len=22), intent(in) :: decoded
|
||||
integer, intent(in) :: nap
|
||||
real, intent(in) :: qual
|
||||
character*2 annot
|
||||
character*22 decoded0
|
||||
|
||||
decoded0=decoded
|
||||
annot=' '
|
||||
if(nap.ne.0) then
|
||||
write(annot,'(a1,i1)') 'a',nap
|
||||
if(qual.lt.0.17) decoded0(22:22)='?'
|
||||
endif
|
||||
write(*,1000) params%nutc,snr,dt,nint(freq),decoded0,annot
|
||||
1000 format(i6.6,i4,f5.1,i5,' ~ ',1x,a22,1x,a2)
|
||||
write(13,1002) params%nutc,nint(sync),snr,dt,freq,0,decoded0
|
||||
1002 format(i6.6,i4,i5,f6.1,f8.0,i4,3x,a22,' FT8')
|
||||
call flush(6)
|
||||
call flush(13)
|
||||
|
||||
select type(this)
|
||||
type is (counting_ft8_decoder)
|
||||
this%decoded = this%decoded + 1
|
||||
end select
|
||||
|
||||
return
|
||||
end subroutine ft8_decoded
|
||||
|
||||
end subroutine multimode_decoder
|
||||
@@ -0,0 +1,24 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_RANDOM_DEFAULT_RANDOM_ENGINE_HPP
|
||||
#define BOOST_COMPUTE_RANDOM_DEFAULT_RANDOM_ENGINE_HPP
|
||||
|
||||
#include <boost/compute/random/mersenne_twister_engine.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
typedef mt19937 default_random_engine;
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_RANDOM_DEFAULT_RANDOM_ENGINE_HPP
|
||||
@@ -0,0 +1,165 @@
|
||||
|
||||
// Copyright Aleksey Gurtovoy 2000-2004
|
||||
//
|
||||
// Distributed under the 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/mpl for documentation.
|
||||
|
||||
// $Id$
|
||||
// $Date$
|
||||
// $Revision$
|
||||
|
||||
// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION!
|
||||
|
||||
#if !defined(BOOST_MPL_PREPROCESSING_MODE)
|
||||
# include <boost/mpl/bool.hpp>
|
||||
# include <boost/mpl/aux_/nested_type_wknd.hpp>
|
||||
# include <boost/mpl/aux_/na_spec.hpp>
|
||||
# include <boost/mpl/aux_/lambda_support.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/mpl/limits/arity.hpp>
|
||||
#include <boost/mpl/aux_/preprocessor/params.hpp>
|
||||
#include <boost/mpl/aux_/preprocessor/ext_params.hpp>
|
||||
#include <boost/mpl/aux_/preprocessor/def_params_tail.hpp>
|
||||
#include <boost/mpl/aux_/preprocessor/enum.hpp>
|
||||
#include <boost/mpl/aux_/preprocessor/sub.hpp>
|
||||
#include <boost/mpl/aux_/config/ctps.hpp>
|
||||
#include <boost/mpl/aux_/config/workaround.hpp>
|
||||
|
||||
#include <boost/preprocessor/dec.hpp>
|
||||
#include <boost/preprocessor/inc.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
|
||||
namespace boost { namespace mpl {
|
||||
|
||||
# define AUX778076_PARAMS(param, sub) \
|
||||
BOOST_MPL_PP_PARAMS( \
|
||||
BOOST_MPL_PP_SUB(BOOST_MPL_LIMIT_METAFUNCTION_ARITY, sub) \
|
||||
, param \
|
||||
) \
|
||||
/**/
|
||||
|
||||
# define AUX778076_SHIFTED_PARAMS(param, sub) \
|
||||
BOOST_MPL_PP_EXT_PARAMS( \
|
||||
2, BOOST_MPL_PP_SUB(BOOST_PP_INC(BOOST_MPL_LIMIT_METAFUNCTION_ARITY), sub) \
|
||||
, param \
|
||||
) \
|
||||
/**/
|
||||
|
||||
# define AUX778076_SPEC_PARAMS(param) \
|
||||
BOOST_MPL_PP_ENUM( \
|
||||
BOOST_PP_DEC(BOOST_MPL_LIMIT_METAFUNCTION_ARITY) \
|
||||
, param \
|
||||
) \
|
||||
/**/
|
||||
|
||||
namespace aux {
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
|
||||
template< bool C_, AUX778076_PARAMS(typename T, 1) >
|
||||
struct BOOST_PP_CAT(AUX778076_OP_NAME,impl)
|
||||
: BOOST_PP_CAT(AUX778076_OP_VALUE1,_)
|
||||
{
|
||||
};
|
||||
|
||||
template< AUX778076_PARAMS(typename T, 1) >
|
||||
struct BOOST_PP_CAT(AUX778076_OP_NAME,impl)< AUX778076_OP_VALUE2,AUX778076_PARAMS(T, 1) >
|
||||
: BOOST_PP_CAT(AUX778076_OP_NAME,impl)<
|
||||
BOOST_MPL_AUX_NESTED_TYPE_WKND(T1)::value
|
||||
, AUX778076_SHIFTED_PARAMS(T, 1)
|
||||
, BOOST_PP_CAT(AUX778076_OP_VALUE2,_)
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BOOST_PP_CAT(AUX778076_OP_NAME,impl)<
|
||||
AUX778076_OP_VALUE2
|
||||
, AUX778076_SPEC_PARAMS(BOOST_PP_CAT(AUX778076_OP_VALUE2,_))
|
||||
>
|
||||
: BOOST_PP_CAT(AUX778076_OP_VALUE2,_)
|
||||
{
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template< bool C_ > struct BOOST_PP_CAT(AUX778076_OP_NAME,impl)
|
||||
{
|
||||
template< AUX778076_PARAMS(typename T, 1) > struct result_
|
||||
: BOOST_PP_CAT(AUX778076_OP_VALUE1,_)
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct BOOST_PP_CAT(AUX778076_OP_NAME,impl)<AUX778076_OP_VALUE2>
|
||||
{
|
||||
template< AUX778076_PARAMS(typename T, 1) > struct result_
|
||||
: BOOST_PP_CAT(AUX778076_OP_NAME,impl)<
|
||||
BOOST_MPL_AUX_NESTED_TYPE_WKND(T1)::value
|
||||
>::template result_< AUX778076_SHIFTED_PARAMS(T,1),BOOST_PP_CAT(AUX778076_OP_VALUE2,_) >
|
||||
{
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
|
||||
template<> struct result_<AUX778076_SPEC_PARAMS(BOOST_PP_CAT(AUX778076_OP_VALUE2,_))>
|
||||
: BOOST_PP_CAT(AUX778076_OP_VALUE2,_)
|
||||
{
|
||||
};
|
||||
};
|
||||
#else
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BOOST_PP_CAT(AUX778076_OP_NAME,impl)<AUX778076_OP_VALUE2>
|
||||
::result_< AUX778076_SPEC_PARAMS(BOOST_PP_CAT(AUX778076_OP_VALUE2,_)) >
|
||||
: BOOST_PP_CAT(AUX778076_OP_VALUE2,_)
|
||||
{
|
||||
};
|
||||
#endif // BOOST_MSVC == 1300
|
||||
|
||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
} // namespace aux
|
||||
|
||||
template<
|
||||
typename BOOST_MPL_AUX_NA_PARAM(T1)
|
||||
, typename BOOST_MPL_AUX_NA_PARAM(T2)
|
||||
BOOST_MPL_PP_DEF_PARAMS_TAIL(2, typename T, BOOST_PP_CAT(AUX778076_OP_VALUE2,_))
|
||||
>
|
||||
struct AUX778076_OP_NAME
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
: aux::BOOST_PP_CAT(AUX778076_OP_NAME,impl)<
|
||||
BOOST_MPL_AUX_NESTED_TYPE_WKND(T1)::value
|
||||
, AUX778076_SHIFTED_PARAMS(T,0)
|
||||
>
|
||||
#else
|
||||
: aux::BOOST_PP_CAT(AUX778076_OP_NAME,impl)<
|
||||
BOOST_MPL_AUX_NESTED_TYPE_WKND(T1)::value
|
||||
>::template result_< AUX778076_SHIFTED_PARAMS(T,0) >
|
||||
#endif
|
||||
{
|
||||
BOOST_MPL_AUX_LAMBDA_SUPPORT(
|
||||
BOOST_MPL_LIMIT_METAFUNCTION_ARITY
|
||||
, AUX778076_OP_NAME
|
||||
, (AUX778076_PARAMS(T, 0))
|
||||
)
|
||||
};
|
||||
|
||||
BOOST_MPL_AUX_NA_SPEC2(
|
||||
2
|
||||
, BOOST_MPL_LIMIT_METAFUNCTION_ARITY
|
||||
, AUX778076_OP_NAME
|
||||
)
|
||||
|
||||
}}
|
||||
|
||||
#undef AUX778076_SPEC_PARAMS
|
||||
#undef AUX778076_SHIFTED_PARAMS
|
||||
#undef AUX778076_PARAMS
|
||||
#undef AUX778076_OP_NAME
|
||||
#undef AUX778076_OP_VALUE1
|
||||
#undef AUX778076_OP_VALUE2
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,96 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
This is an auto-generated file. Do not edit!
|
||||
==============================================================================*/
|
||||
namespace boost { namespace fusion { namespace detail
|
||||
{
|
||||
template <typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9>
|
||||
struct list_to_cons
|
||||
{
|
||||
typedef T0 head_type;
|
||||
typedef list_to_cons<
|
||||
T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9, void_>
|
||||
tail_list_to_cons;
|
||||
typedef typename tail_list_to_cons::type tail_type;
|
||||
typedef cons<head_type, tail_type> type;
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static type
|
||||
call(typename detail::call_param<T0 >::type arg0)
|
||||
{
|
||||
return type(arg0
|
||||
);
|
||||
}
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static type
|
||||
call(typename detail::call_param<T0 >::type arg0 , typename detail::call_param<T1 >::type arg1)
|
||||
{
|
||||
return type(arg0
|
||||
, tail_list_to_cons::call(arg1));
|
||||
}
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static type
|
||||
call(typename detail::call_param<T0 >::type arg0 , typename detail::call_param<T1 >::type arg1 , typename detail::call_param<T2 >::type arg2)
|
||||
{
|
||||
return type(arg0
|
||||
, tail_list_to_cons::call(arg1 , arg2));
|
||||
}
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static type
|
||||
call(typename detail::call_param<T0 >::type arg0 , typename detail::call_param<T1 >::type arg1 , typename detail::call_param<T2 >::type arg2 , typename detail::call_param<T3 >::type arg3)
|
||||
{
|
||||
return type(arg0
|
||||
, tail_list_to_cons::call(arg1 , arg2 , arg3));
|
||||
}
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static type
|
||||
call(typename detail::call_param<T0 >::type arg0 , typename detail::call_param<T1 >::type arg1 , typename detail::call_param<T2 >::type arg2 , typename detail::call_param<T3 >::type arg3 , typename detail::call_param<T4 >::type arg4)
|
||||
{
|
||||
return type(arg0
|
||||
, tail_list_to_cons::call(arg1 , arg2 , arg3 , arg4));
|
||||
}
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static type
|
||||
call(typename detail::call_param<T0 >::type arg0 , typename detail::call_param<T1 >::type arg1 , typename detail::call_param<T2 >::type arg2 , typename detail::call_param<T3 >::type arg3 , typename detail::call_param<T4 >::type arg4 , typename detail::call_param<T5 >::type arg5)
|
||||
{
|
||||
return type(arg0
|
||||
, tail_list_to_cons::call(arg1 , arg2 , arg3 , arg4 , arg5));
|
||||
}
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static type
|
||||
call(typename detail::call_param<T0 >::type arg0 , typename detail::call_param<T1 >::type arg1 , typename detail::call_param<T2 >::type arg2 , typename detail::call_param<T3 >::type arg3 , typename detail::call_param<T4 >::type arg4 , typename detail::call_param<T5 >::type arg5 , typename detail::call_param<T6 >::type arg6)
|
||||
{
|
||||
return type(arg0
|
||||
, tail_list_to_cons::call(arg1 , arg2 , arg3 , arg4 , arg5 , arg6));
|
||||
}
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static type
|
||||
call(typename detail::call_param<T0 >::type arg0 , typename detail::call_param<T1 >::type arg1 , typename detail::call_param<T2 >::type arg2 , typename detail::call_param<T3 >::type arg3 , typename detail::call_param<T4 >::type arg4 , typename detail::call_param<T5 >::type arg5 , typename detail::call_param<T6 >::type arg6 , typename detail::call_param<T7 >::type arg7)
|
||||
{
|
||||
return type(arg0
|
||||
, tail_list_to_cons::call(arg1 , arg2 , arg3 , arg4 , arg5 , arg6 , arg7));
|
||||
}
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static type
|
||||
call(typename detail::call_param<T0 >::type arg0 , typename detail::call_param<T1 >::type arg1 , typename detail::call_param<T2 >::type arg2 , typename detail::call_param<T3 >::type arg3 , typename detail::call_param<T4 >::type arg4 , typename detail::call_param<T5 >::type arg5 , typename detail::call_param<T6 >::type arg6 , typename detail::call_param<T7 >::type arg7 , typename detail::call_param<T8 >::type arg8)
|
||||
{
|
||||
return type(arg0
|
||||
, tail_list_to_cons::call(arg1 , arg2 , arg3 , arg4 , arg5 , arg6 , arg7 , arg8));
|
||||
}
|
||||
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||
static type
|
||||
call(typename detail::call_param<T0 >::type arg0 , typename detail::call_param<T1 >::type arg1 , typename detail::call_param<T2 >::type arg2 , typename detail::call_param<T3 >::type arg3 , typename detail::call_param<T4 >::type arg4 , typename detail::call_param<T5 >::type arg5 , typename detail::call_param<T6 >::type arg6 , typename detail::call_param<T7 >::type arg7 , typename detail::call_param<T8 >::type arg8 , typename detail::call_param<T9 >::type arg9)
|
||||
{
|
||||
return type(arg0
|
||||
, tail_list_to_cons::call(arg1 , arg2 , arg3 , arg4 , arg5 , arg6 , arg7 , arg8 , arg9));
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct list_to_cons<void_ , void_ , void_ , void_ , void_ , void_ , void_ , void_ , void_ , void_>
|
||||
{
|
||||
typedef nil_ type;
|
||||
};
|
||||
}}}
|
||||
@@ -0,0 +1,415 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
|
||||
#define BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/uses_allocator.hpp>
|
||||
|
||||
#include <boost/container/detail/addressof.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/pair.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/move/detail/fwd_macros.hpp>
|
||||
#endif
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
|
||||
namespace boost { namespace container {
|
||||
|
||||
namespace container_detail {
|
||||
|
||||
|
||||
// Check if we can detect is_convertible using advanced SFINAE expressions
|
||||
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
//! Code inspired by Mathias Gaunard's is_convertible.cpp found in the Boost mailing list
|
||||
//! http://boost.2283326.n4.nabble.com/type-traits-is-constructible-when-decltype-is-supported-td3575452.html
|
||||
//! Thanks Mathias!
|
||||
|
||||
//With variadic templates, we need a single class to implement the trait
|
||||
template<class T, class ...Args>
|
||||
struct is_constructible
|
||||
{
|
||||
typedef char yes_type;
|
||||
struct no_type
|
||||
{ char padding[2]; };
|
||||
|
||||
template<std::size_t N>
|
||||
struct dummy;
|
||||
|
||||
template<class X>
|
||||
static decltype(X(boost::move_detail::declval<Args>()...), true_type()) test(int);
|
||||
|
||||
template<class X>
|
||||
static no_type test(...);
|
||||
|
||||
static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
|
||||
};
|
||||
|
||||
template <class T, class InnerAlloc, class ...Args>
|
||||
struct is_constructible_with_allocator_prefix
|
||||
: is_constructible<T, allocator_arg_t, InnerAlloc, Args...>
|
||||
{};
|
||||
|
||||
#else // #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
//Without advanced SFINAE expressions, we can't use is_constructible
|
||||
//so backup to constructible_with_allocator_xxx
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <class T, class InnerAlloc, class ...Args>
|
||||
struct is_constructible_with_allocator_prefix
|
||||
: constructible_with_allocator_prefix<T>
|
||||
{};
|
||||
|
||||
template <class T, class InnerAlloc, class ...Args>
|
||||
struct is_constructible_with_allocator_suffix
|
||||
: constructible_with_allocator_suffix<T>
|
||||
{};
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
|
||||
struct is_constructible_with_allocator_prefix
|
||||
: constructible_with_allocator_prefix<T>
|
||||
{};
|
||||
|
||||
template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
|
||||
struct is_constructible_with_allocator_suffix
|
||||
: constructible_with_allocator_suffix<T>
|
||||
{};
|
||||
|
||||
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#endif // #if !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, typename T
|
||||
, class ...Args
|
||||
>
|
||||
inline typename container_detail::enable_if_and
|
||||
< void
|
||||
, container_detail::is_not_pair<T>
|
||||
, container_detail::not_< uses_allocator<T, ArgAlloc> >
|
||||
>::type dispatch_uses_allocator
|
||||
( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
|
||||
{
|
||||
(void)arg_alloc;
|
||||
allocator_traits<ConstructAlloc>::construct(construct_alloc, p, ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// allocator_arg_t
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, typename T
|
||||
, class ...Args
|
||||
>
|
||||
inline typename container_detail::enable_if_and
|
||||
< void
|
||||
, container_detail::is_not_pair<T>
|
||||
, uses_allocator<T, ArgAlloc>
|
||||
, is_constructible_with_allocator_prefix<T, ArgAlloc, Args...>
|
||||
>::type dispatch_uses_allocator
|
||||
( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args) ...args)
|
||||
{
|
||||
allocator_traits<ConstructAlloc>::construct
|
||||
( construct_alloc, p, allocator_arg
|
||||
, ::boost::forward<ArgAlloc>(arg_alloc), ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// allocator suffix
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, typename T
|
||||
, class ...Args
|
||||
>
|
||||
inline typename container_detail::enable_if_and
|
||||
< void
|
||||
, container_detail::is_not_pair<T>
|
||||
, uses_allocator<T, ArgAlloc>
|
||||
, container_detail::not_<is_constructible_with_allocator_prefix<T, ArgAlloc, Args...> >
|
||||
>::type dispatch_uses_allocator
|
||||
( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
|
||||
{
|
||||
allocator_traits<ConstructAlloc>::construct
|
||||
(construct_alloc, p, ::boost::forward<Args>(args)..., ::boost::forward<ArgAlloc>(arg_alloc));
|
||||
}
|
||||
|
||||
#else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
|
||||
template <typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
inline typename container_detail::enable_if_and\
|
||||
< void\
|
||||
, container_detail::is_not_pair<T>\
|
||||
, container_detail::not_<uses_allocator<T, ArgAlloc> >\
|
||||
>::type\
|
||||
dispatch_uses_allocator\
|
||||
(ConstructAlloc &construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
(void)arg_alloc;\
|
||||
allocator_traits<ConstructAlloc>::construct(construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
|
||||
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
|
||||
|
||||
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
|
||||
template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
inline typename container_detail::enable_if_and\
|
||||
< void\
|
||||
, container_detail::is_not_pair<T>\
|
||||
, uses_allocator<T, ArgAlloc>\
|
||||
, is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N>\
|
||||
>::type\
|
||||
dispatch_uses_allocator\
|
||||
(ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
allocator_traits<ConstructAlloc>::construct\
|
||||
(construct_alloc, p, allocator_arg, ::boost::forward<ArgAlloc>(arg_alloc) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
|
||||
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
|
||||
|
||||
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
|
||||
template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
inline typename container_detail::enable_if_and\
|
||||
< void\
|
||||
, container_detail::is_not_pair<T>\
|
||||
, uses_allocator<T, ArgAlloc>\
|
||||
, container_detail::not_<is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N> >\
|
||||
>::type\
|
||||
dispatch_uses_allocator\
|
||||
(ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
allocator_traits<ConstructAlloc>::construct\
|
||||
(construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N, ::boost::forward<ArgAlloc>(arg_alloc));\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
|
||||
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
|
||||
|
||||
#endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, typename Pair
|
||||
> inline
|
||||
BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if<container_detail::is_pair<Pair> >::type)
|
||||
dispatch_uses_allocator
|
||||
( ConstructAlloc & construct_alloc
|
||||
, BOOST_FWD_REF(ArgAlloc) arg_alloc
|
||||
, Pair* p)
|
||||
{
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first));
|
||||
BOOST_TRY{
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->second));
|
||||
}
|
||||
BOOST_CATCH(...) {
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(p->first));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, class Pair, class U, class V>
|
||||
BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if<container_detail::is_pair<Pair> >::type)
|
||||
dispatch_uses_allocator
|
||||
( ConstructAlloc & construct_alloc
|
||||
, BOOST_FWD_REF(ArgAlloc) arg_alloc
|
||||
, Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
|
||||
{
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first), ::boost::forward<U>(x));
|
||||
BOOST_TRY{
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->second), ::boost::forward<V>(y));
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(p->first));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, class Pair, class Pair2>
|
||||
BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if< container_detail::is_pair<Pair> >::type)
|
||||
dispatch_uses_allocator
|
||||
(ConstructAlloc & construct_alloc
|
||||
, BOOST_FWD_REF(ArgAlloc) arg_alloc
|
||||
, Pair* p, Pair2& x)
|
||||
{ (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, x.first, x.second); }
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, class Pair, class Pair2>
|
||||
typename container_detail::enable_if_and
|
||||
< void
|
||||
, container_detail::is_pair<Pair>
|
||||
, container_detail::not_<boost::move_detail::is_reference<Pair2> > >::type //This is needed for MSVC10 and ambiguous overloads
|
||||
dispatch_uses_allocator
|
||||
(ConstructAlloc & construct_alloc
|
||||
, BOOST_FWD_REF(ArgAlloc) arg_alloc
|
||||
, Pair* p, BOOST_RV_REF_BEG Pair2 BOOST_RV_REF_END x)
|
||||
{ (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, ::boost::move(x.first), ::boost::move(x.second)); }
|
||||
|
||||
|
||||
//piecewise construction from boost::tuple
|
||||
#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE(N,M)\
|
||||
template< typename ConstructAlloc, typename ArgAlloc, class Pair \
|
||||
, template<class, class, class, class, class, class, class, class, class, class> class BoostTuple \
|
||||
BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
|
||||
typename container_detail::enable_if< container_detail::is_pair<Pair> >::type\
|
||||
dispatch_uses_allocator( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t\
|
||||
, BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> p\
|
||||
, BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q)\
|
||||
{\
|
||||
(void)p; (void)q;\
|
||||
(dispatch_uses_allocator)\
|
||||
(construct_alloc, arg_alloc, container_detail::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_TMPL_GET##N);\
|
||||
BOOST_TRY{\
|
||||
(dispatch_uses_allocator)\
|
||||
(construct_alloc, arg_alloc, container_detail::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_TMPL_GETQ##M);\
|
||||
}\
|
||||
BOOST_CATCH(...) {\
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(pair->first));\
|
||||
BOOST_RETHROW\
|
||||
}\
|
||||
BOOST_CATCH_END\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE)
|
||||
#undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE
|
||||
|
||||
//piecewise construction from Std Tuple
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template< typename ConstructAlloc, typename ArgAlloc, class Pair
|
||||
, template<class ...> class Tuple, class... Args1, class... Args2, size_t... Indexes1, size_t... Indexes2>
|
||||
void dispatch_uses_allocator_index( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair
|
||||
, Tuple<Args1...>& t1, Tuple<Args2...>& t2, index_tuple<Indexes1...>, index_tuple<Indexes2...>)
|
||||
{
|
||||
(void)t1; (void)t2;
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(pair->first), ::boost::forward<Args1>(get<Indexes1>(t1))...);
|
||||
BOOST_TRY{
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(pair->second), ::boost::forward<Args2>(get<Indexes2>(t2))...);
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(pair->first));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
template< typename ConstructAlloc, typename ArgAlloc, class Pair
|
||||
, template<class ...> class Tuple, class... Args1, class... Args2>
|
||||
typename container_detail::enable_if< container_detail::is_pair<Pair> >::type
|
||||
dispatch_uses_allocator( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t
|
||||
, Tuple<Args1...> t1, Tuple<Args2...> t2)
|
||||
{
|
||||
(dispatch_uses_allocator_index)( construct_alloc, arg_alloc, pair, t1, t2
|
||||
, typename build_number_seq<sizeof...(Args1)>::type()
|
||||
, typename build_number_seq<sizeof...(Args2)>::type());
|
||||
}
|
||||
|
||||
#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
|
||||
|
||||
//MSVC 2010 tuple implementation
|
||||
#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE(N,M)\
|
||||
template< typename ConstructAlloc, typename ArgAlloc, class Pair\
|
||||
, template<class, class, class, class, class, class, class, class, class, class> class StdTuple\
|
||||
BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
|
||||
typename container_detail::enable_if< container_detail::is_pair<Pair> >::type\
|
||||
dispatch_uses_allocator(ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t\
|
||||
, StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::std::tr1::_Nil)> p\
|
||||
, StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::std::tr1::_Nil)> q)\
|
||||
{\
|
||||
(void)p; (void)q;\
|
||||
(dispatch_uses_allocator)\
|
||||
(construct_alloc, arg_alloc, container_detail::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
|
||||
BOOST_TRY{\
|
||||
(dispatch_uses_allocator)\
|
||||
(construct_alloc, arg_alloc, container_detail::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
|
||||
}\
|
||||
BOOST_CATCH(...) {\
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(pair->first));\
|
||||
BOOST_RETHROW\
|
||||
}\
|
||||
BOOST_CATCH_END\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE)
|
||||
#undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
|
||||
|
||||
#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
|
||||
#if _VARIADIC_MAX >= 9
|
||||
#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT 9
|
||||
#else
|
||||
#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT BOOST_MOVE_ADD(_VARIADIC_MAX, 1)
|
||||
#endif
|
||||
|
||||
//MSVC 2012 tuple implementation
|
||||
#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE(N,M)\
|
||||
template< typename ConstructAlloc, typename ArgAlloc, class Pair\
|
||||
, template<BOOST_MOVE_REPEAT(_VARIADIC_MAX, class), class, class, class> class StdTuple \
|
||||
BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
|
||||
typename container_detail::enable_if< container_detail::is_pair<Pair> >::type\
|
||||
dispatch_uses_allocator\
|
||||
( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t\
|
||||
, StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),N),::std::_Nil) > p\
|
||||
, StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),M),::std::_Nil) > q)\
|
||||
{\
|
||||
(void)p; (void)q;\
|
||||
(dispatch_uses_allocator)\
|
||||
(construct_alloc, arg_alloc, container_detail::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
|
||||
BOOST_TRY{\
|
||||
(dispatch_uses_allocator)\
|
||||
(construct_alloc, arg_alloc, container_detail::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
|
||||
}\
|
||||
BOOST_CATCH(...) {\
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(pair->first));\
|
||||
BOOST_RETHROW\
|
||||
}\
|
||||
BOOST_CATCH_END\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITER2D_0TOMAX(BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE)
|
||||
#undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
|
||||
#undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT
|
||||
|
||||
#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
} //namespace container_detail
|
||||
|
||||
}} // namespace boost { namespace container {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef BOOST_SERIALIZATION_UTILITY_HPP
|
||||
#define BOOST_SERIALIZATION_UTILITY_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// serialization/utility.hpp:
|
||||
// serialization for stl utility templates
|
||||
|
||||
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
// 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 http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <utility>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/is_bitwise_serializable.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
// pair
|
||||
template<class Archive, class F, class S>
|
||||
inline void serialize(
|
||||
Archive & ar,
|
||||
std::pair<F, S> & p,
|
||||
const unsigned int /* file_version */
|
||||
){
|
||||
// note: we remove any const-ness on the first argument. The reason is that
|
||||
// for stl maps, the type saved is pair<const key, T). We remove
|
||||
// the const-ness in order to be able to load it.
|
||||
typedef typename boost::remove_const<F>::type typef;
|
||||
ar & boost::serialization::make_nvp("first", const_cast<typef &>(p.first));
|
||||
ar & boost::serialization::make_nvp("second", p.second);
|
||||
}
|
||||
|
||||
/// specialization of is_bitwise_serializable for pairs
|
||||
template <class T, class U>
|
||||
struct is_bitwise_serializable<std::pair<T,U> >
|
||||
: public mpl::and_<is_bitwise_serializable< T >,is_bitwise_serializable<U> >
|
||||
{
|
||||
};
|
||||
|
||||
} // serialization
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_SERIALIZATION_UTILITY_HPP
|
||||
@@ -0,0 +1,18 @@
|
||||
/* MOD2CONVERT.H - Routines converting between sparse and dense mod2 matrices.*/
|
||||
|
||||
/* Copyright (c) 1995-2012 by Radford M. Neal.
|
||||
*
|
||||
* Permission is granted for anyone to copy, use, modify, and distribute
|
||||
* these programs and accompanying documents for any purpose, provided
|
||||
* this copyright notice is retained and prominently displayed, and note
|
||||
* is made of any changes made to these programs. These programs and
|
||||
* documents are distributed without any warranty, express or implied.
|
||||
* As the programs were written for research purposes only, they have not
|
||||
* been tested to the degree that would be advisable in any important
|
||||
* application. All use of these programs is entirely at the user's own
|
||||
* risk.
|
||||
*/
|
||||
|
||||
|
||||
void mod2sparse_to_dense (mod2sparse *, mod2dense *);
|
||||
void mod2dense_to_sparse (mod2dense *, mod2sparse *);
|
||||
@@ -0,0 +1,856 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_ALGORITHM_COPY_HPP
|
||||
#define BOOST_COMPUTE_ALGORITHM_COPY_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
|
||||
#include <boost/compute/buffer.hpp>
|
||||
#include <boost/compute/system.hpp>
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/algorithm/detail/copy_on_device.hpp>
|
||||
#include <boost/compute/algorithm/detail/copy_to_device.hpp>
|
||||
#include <boost/compute/algorithm/detail/copy_to_host.hpp>
|
||||
#include <boost/compute/async/future.hpp>
|
||||
#include <boost/compute/container/mapped_view.hpp>
|
||||
#include <boost/compute/detail/device_ptr.hpp>
|
||||
#include <boost/compute/detail/is_contiguous_iterator.hpp>
|
||||
#include <boost/compute/detail/iterator_range_size.hpp>
|
||||
#include <boost/compute/detail/parameter_cache.hpp>
|
||||
#include <boost/compute/iterator/buffer_iterator.hpp>
|
||||
#include <boost/compute/type_traits/type_name.hpp>
|
||||
#include <boost/compute/type_traits/is_device_iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
namespace detail {
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
|
||||
// meta-function returning true if copy() between InputIterator and
|
||||
// OutputIterator can be implemented with clEnqueueCopyBuffer().
|
||||
template<class InputIterator, class OutputIterator>
|
||||
struct can_copy_with_copy_buffer :
|
||||
mpl::and_<
|
||||
mpl::or_<
|
||||
boost::is_same<
|
||||
InputIterator,
|
||||
buffer_iterator<typename InputIterator::value_type>
|
||||
>,
|
||||
boost::is_same<
|
||||
InputIterator,
|
||||
detail::device_ptr<typename InputIterator::value_type>
|
||||
>
|
||||
>,
|
||||
mpl::or_<
|
||||
boost::is_same<
|
||||
OutputIterator,
|
||||
buffer_iterator<typename OutputIterator::value_type>
|
||||
>,
|
||||
boost::is_same<
|
||||
OutputIterator,
|
||||
detail::device_ptr<typename OutputIterator::value_type>
|
||||
>
|
||||
>,
|
||||
boost::is_same<
|
||||
typename InputIterator::value_type,
|
||||
typename OutputIterator::value_type
|
||||
>
|
||||
>::type {};
|
||||
|
||||
// meta-function returning true if value_types of HostIterator and
|
||||
// DeviceIterator are same
|
||||
template<class HostIterator, class DeviceIterator>
|
||||
struct is_same_value_type :
|
||||
boost::is_same<
|
||||
typename boost::remove_cv<
|
||||
typename std::iterator_traits<HostIterator>::value_type
|
||||
>::type,
|
||||
typename boost::remove_cv<
|
||||
typename DeviceIterator::value_type
|
||||
>::type
|
||||
>::type {};
|
||||
|
||||
// meta-function returning true if value_type of HostIterator is bool
|
||||
template<class HostIterator>
|
||||
struct is_bool_value_type :
|
||||
boost::is_same<
|
||||
typename boost::remove_cv<
|
||||
typename std::iterator_traits<HostIterator>::value_type
|
||||
>::type,
|
||||
bool
|
||||
>::type {};
|
||||
|
||||
// host -> device (async)
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline future<OutputIterator>
|
||||
dispatch_copy_async(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
mpl::not_<
|
||||
is_device_iterator<InputIterator>
|
||||
>,
|
||||
is_device_iterator<OutputIterator>,
|
||||
is_same_value_type<InputIterator, OutputIterator>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
is_contiguous_iterator<InputIterator>::value,
|
||||
"copy_async() is only supported for contiguous host iterators"
|
||||
);
|
||||
|
||||
return copy_to_device_async(first, last, result, queue);
|
||||
}
|
||||
|
||||
// host -> device (async)
|
||||
// Type mismatch between InputIterator and OutputIterator value_types
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline future<OutputIterator>
|
||||
dispatch_copy_async(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
mpl::not_<
|
||||
is_device_iterator<InputIterator>
|
||||
>,
|
||||
is_device_iterator<OutputIterator>,
|
||||
mpl::not_<
|
||||
is_same_value_type<InputIterator, OutputIterator>
|
||||
>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
is_contiguous_iterator<InputIterator>::value,
|
||||
"copy_async() is only supported for contiguous host iterators"
|
||||
);
|
||||
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type input_type;
|
||||
|
||||
const context &context = queue.get_context();
|
||||
size_t count = iterator_range_size(first, last);
|
||||
|
||||
if(count < size_t(1)) {
|
||||
return future<OutputIterator>();
|
||||
}
|
||||
|
||||
// map [first; last) to device and run copy kernel
|
||||
// on device for copying & casting
|
||||
::boost::compute::mapped_view<input_type> mapped_host(
|
||||
// make sure it's a pointer to constant data
|
||||
// to force read only mapping
|
||||
const_cast<const input_type*>(
|
||||
::boost::addressof(*first)
|
||||
),
|
||||
count,
|
||||
context
|
||||
);
|
||||
return copy_on_device_async(
|
||||
mapped_host.begin(), mapped_host.end(), result, queue
|
||||
);
|
||||
}
|
||||
|
||||
// host -> device
|
||||
// InputIterator is a contiguous iterator
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline OutputIterator
|
||||
dispatch_copy(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
mpl::not_<
|
||||
is_device_iterator<InputIterator>
|
||||
>,
|
||||
is_device_iterator<OutputIterator>,
|
||||
is_same_value_type<InputIterator, OutputIterator>,
|
||||
is_contiguous_iterator<InputIterator>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
return copy_to_device(first, last, result, queue);
|
||||
}
|
||||
|
||||
// host -> device
|
||||
// Type mismatch between InputIterator and OutputIterator value_types
|
||||
// InputIterator is a contiguous iterator
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline OutputIterator
|
||||
dispatch_copy(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
mpl::not_<
|
||||
is_device_iterator<InputIterator>
|
||||
>,
|
||||
is_device_iterator<OutputIterator>,
|
||||
mpl::not_<
|
||||
is_same_value_type<InputIterator, OutputIterator>
|
||||
>,
|
||||
is_contiguous_iterator<InputIterator>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
typedef typename OutputIterator::value_type output_type;
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type input_type;
|
||||
|
||||
const device &device = queue.get_device();
|
||||
|
||||
// loading parameters
|
||||
std::string cache_key =
|
||||
std::string("__boost_compute_copy_to_device_")
|
||||
+ type_name<input_type>() + "_" + type_name<output_type>();
|
||||
boost::shared_ptr<parameter_cache> parameters =
|
||||
detail::parameter_cache::get_global_cache(device);
|
||||
|
||||
size_t map_copy_threshold;
|
||||
size_t direct_copy_threshold;
|
||||
|
||||
// calculate default values of thresholds
|
||||
if (device.type() & device::gpu) {
|
||||
// GPUs
|
||||
map_copy_threshold = 524288; // 0.5 MB
|
||||
direct_copy_threshold = 52428800; // 50 MB
|
||||
}
|
||||
else {
|
||||
// CPUs and other devices
|
||||
map_copy_threshold = 134217728; // 128 MB
|
||||
direct_copy_threshold = 0; // it's never efficient for CPUs
|
||||
}
|
||||
|
||||
// load thresholds
|
||||
map_copy_threshold =
|
||||
parameters->get(
|
||||
cache_key, "map_copy_threshold", map_copy_threshold
|
||||
);
|
||||
direct_copy_threshold =
|
||||
parameters->get(
|
||||
cache_key, "direct_copy_threshold", direct_copy_threshold
|
||||
);
|
||||
|
||||
// select copy method based on thresholds & input_size_bytes
|
||||
size_t count = iterator_range_size(first, last);
|
||||
size_t input_size_bytes = count * sizeof(input_type);
|
||||
|
||||
// [0; map_copy_threshold) -> copy_to_device_map()
|
||||
if(input_size_bytes < map_copy_threshold) {
|
||||
return copy_to_device_map(first, last, result, queue);
|
||||
}
|
||||
// [map_copy_threshold; direct_copy_threshold) -> convert [first; last)
|
||||
// on host and then perform copy_to_device()
|
||||
else if(input_size_bytes < direct_copy_threshold) {
|
||||
std::vector<output_type> vector(first, last);
|
||||
return copy_to_device(vector.begin(), vector.end(), result, queue);
|
||||
}
|
||||
|
||||
// [direct_copy_threshold; inf) -> map [first; last) to device and
|
||||
// run copy kernel on device for copying & casting
|
||||
// At this point we are sure that count > 1 (first != last).
|
||||
|
||||
// Perform async copy to device, wait for it to be finished and
|
||||
// return the result.
|
||||
// At this point we are sure that count > 1 (first != last), so event
|
||||
// returned by dispatch_copy_async() must be valid.
|
||||
return dispatch_copy_async(first, last, result, queue).get();
|
||||
}
|
||||
|
||||
// host -> device
|
||||
// InputIterator is NOT a contiguous iterator
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline OutputIterator
|
||||
dispatch_copy(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
mpl::not_<
|
||||
is_device_iterator<InputIterator>
|
||||
>,
|
||||
is_device_iterator<OutputIterator>,
|
||||
mpl::not_<
|
||||
is_contiguous_iterator<InputIterator>
|
||||
>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
typedef typename OutputIterator::value_type output_type;
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type input_type;
|
||||
|
||||
const device &device = queue.get_device();
|
||||
|
||||
// loading parameters
|
||||
std::string cache_key =
|
||||
std::string("__boost_compute_copy_to_device_")
|
||||
+ type_name<input_type>() + "_" + type_name<output_type>();
|
||||
boost::shared_ptr<parameter_cache> parameters =
|
||||
detail::parameter_cache::get_global_cache(device);
|
||||
|
||||
size_t map_copy_threshold;
|
||||
size_t direct_copy_threshold;
|
||||
|
||||
// calculate default values of thresholds
|
||||
if (device.type() & device::gpu) {
|
||||
// GPUs
|
||||
map_copy_threshold = 524288; // 0.5 MB
|
||||
direct_copy_threshold = 52428800; // 50 MB
|
||||
}
|
||||
else {
|
||||
// CPUs and other devices
|
||||
map_copy_threshold = 134217728; // 128 MB
|
||||
direct_copy_threshold = 0; // it's never efficient for CPUs
|
||||
}
|
||||
|
||||
// load thresholds
|
||||
map_copy_threshold =
|
||||
parameters->get(
|
||||
cache_key, "map_copy_threshold", map_copy_threshold
|
||||
);
|
||||
direct_copy_threshold =
|
||||
parameters->get(
|
||||
cache_key, "direct_copy_threshold", direct_copy_threshold
|
||||
);
|
||||
|
||||
// select copy method based on thresholds & input_size_bytes
|
||||
size_t input_size = iterator_range_size(first, last);
|
||||
size_t input_size_bytes = input_size * sizeof(input_type);
|
||||
|
||||
// [0; map_copy_threshold) -> copy_to_device_map()
|
||||
//
|
||||
// if direct_copy_threshold is less than map_copy_threshold
|
||||
// copy_to_device_map() is used for every input
|
||||
if(input_size_bytes < map_copy_threshold
|
||||
|| direct_copy_threshold <= map_copy_threshold) {
|
||||
return copy_to_device_map(first, last, result, queue);
|
||||
}
|
||||
// [map_copy_threshold; inf) -> convert [first; last)
|
||||
// on host and then perform copy_to_device()
|
||||
std::vector<output_type> vector(first, last);
|
||||
return copy_to_device(vector.begin(), vector.end(), result, queue);
|
||||
}
|
||||
|
||||
// device -> host (async)
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline future<OutputIterator>
|
||||
dispatch_copy_async(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
is_device_iterator<InputIterator>,
|
||||
mpl::not_<
|
||||
is_device_iterator<OutputIterator>
|
||||
>,
|
||||
is_same_value_type<OutputIterator, InputIterator>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
is_contiguous_iterator<OutputIterator>::value,
|
||||
"copy_async() is only supported for contiguous host iterators"
|
||||
);
|
||||
|
||||
return copy_to_host_async(first, last, result, queue);
|
||||
}
|
||||
|
||||
// device -> host (async)
|
||||
// Type mismatch between InputIterator and OutputIterator value_types
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline future<OutputIterator>
|
||||
dispatch_copy_async(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
is_device_iterator<InputIterator>,
|
||||
mpl::not_<
|
||||
is_device_iterator<OutputIterator>
|
||||
>,
|
||||
mpl::not_<
|
||||
is_same_value_type<OutputIterator, InputIterator>
|
||||
>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
is_contiguous_iterator<OutputIterator>::value,
|
||||
"copy_async() is only supported for contiguous host iterators"
|
||||
);
|
||||
|
||||
typedef typename std::iterator_traits<OutputIterator>::value_type output_type;
|
||||
const context &context = queue.get_context();
|
||||
size_t count = iterator_range_size(first, last);
|
||||
|
||||
if(count < size_t(1)) {
|
||||
return future<OutputIterator>();
|
||||
}
|
||||
|
||||
// map host memory to device
|
||||
buffer mapped_host(
|
||||
context,
|
||||
count * sizeof(output_type),
|
||||
buffer::write_only | buffer::use_host_ptr,
|
||||
static_cast<void*>(
|
||||
::boost::addressof(*result)
|
||||
)
|
||||
);
|
||||
// copy async on device
|
||||
::boost::compute::future<buffer_iterator<output_type> > future =
|
||||
copy_on_device_async(
|
||||
first,
|
||||
last,
|
||||
make_buffer_iterator<output_type>(mapped_host),
|
||||
queue
|
||||
);
|
||||
// update host memory asynchronously by maping and unmaping memory
|
||||
event map_event;
|
||||
void* ptr = queue.enqueue_map_buffer_async(
|
||||
mapped_host,
|
||||
CL_MAP_READ,
|
||||
0,
|
||||
count * sizeof(output_type),
|
||||
map_event,
|
||||
future.get_event()
|
||||
);
|
||||
event unmap_event =
|
||||
queue.enqueue_unmap_buffer(mapped_host, ptr, map_event);
|
||||
return make_future(result + count, unmap_event);
|
||||
}
|
||||
|
||||
// device -> host
|
||||
// OutputIterator is a contiguous iterator
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline OutputIterator
|
||||
dispatch_copy(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
is_device_iterator<InputIterator>,
|
||||
mpl::not_<
|
||||
is_device_iterator<OutputIterator>
|
||||
>,
|
||||
is_same_value_type<OutputIterator, InputIterator>,
|
||||
is_contiguous_iterator<OutputIterator>,
|
||||
mpl::not_<
|
||||
is_bool_value_type<OutputIterator>
|
||||
>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
return copy_to_host(first, last, result, queue);
|
||||
}
|
||||
|
||||
// device -> host
|
||||
// Type mismatch between InputIterator and OutputIterator value_types
|
||||
// OutputIterator is NOT a contiguous iterator or value_type of OutputIterator
|
||||
// is a boolean type.
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline OutputIterator
|
||||
dispatch_copy(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
is_device_iterator<InputIterator>,
|
||||
mpl::not_<
|
||||
is_device_iterator<OutputIterator>
|
||||
>,
|
||||
mpl::or_<
|
||||
mpl::not_<
|
||||
is_contiguous_iterator<OutputIterator>
|
||||
>,
|
||||
is_bool_value_type<OutputIterator>
|
||||
>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
typedef typename std::iterator_traits<OutputIterator>::value_type output_type;
|
||||
typedef typename InputIterator::value_type input_type;
|
||||
|
||||
const device &device = queue.get_device();
|
||||
|
||||
// loading parameters
|
||||
std::string cache_key =
|
||||
std::string("__boost_compute_copy_to_host_")
|
||||
+ type_name<input_type>() + "_" + type_name<output_type>();
|
||||
boost::shared_ptr<parameter_cache> parameters =
|
||||
detail::parameter_cache::get_global_cache(device);
|
||||
|
||||
size_t map_copy_threshold;
|
||||
size_t direct_copy_threshold;
|
||||
|
||||
// calculate default values of thresholds
|
||||
if (device.type() & device::gpu) {
|
||||
// GPUs
|
||||
map_copy_threshold = 33554432; // 30 MB
|
||||
direct_copy_threshold = 0; // it's never efficient for GPUs
|
||||
}
|
||||
else {
|
||||
// CPUs and other devices
|
||||
map_copy_threshold = 134217728; // 128 MB
|
||||
direct_copy_threshold = 0; // it's never efficient for CPUs
|
||||
}
|
||||
|
||||
// load thresholds
|
||||
map_copy_threshold =
|
||||
parameters->get(
|
||||
cache_key, "map_copy_threshold", map_copy_threshold
|
||||
);
|
||||
direct_copy_threshold =
|
||||
parameters->get(
|
||||
cache_key, "direct_copy_threshold", direct_copy_threshold
|
||||
);
|
||||
|
||||
// select copy method based on thresholds & input_size_bytes
|
||||
size_t count = iterator_range_size(first, last);
|
||||
size_t input_size_bytes = count * sizeof(input_type);
|
||||
|
||||
// [0; map_copy_threshold) -> copy_to_host_map()
|
||||
//
|
||||
// if direct_copy_threshold is less than map_copy_threshold
|
||||
// copy_to_host_map() is used for every input
|
||||
if(input_size_bytes < map_copy_threshold
|
||||
|| direct_copy_threshold <= map_copy_threshold) {
|
||||
return copy_to_host_map(first, last, result, queue);
|
||||
}
|
||||
// [map_copy_threshold; inf) -> copy [first;last) to temporary vector
|
||||
// then copy (and convert) to result using std::copy()
|
||||
std::vector<input_type> vector(count);
|
||||
copy_to_host(first, last, vector.begin(), queue);
|
||||
return std::copy(vector.begin(), vector.end(), result);
|
||||
}
|
||||
|
||||
// device -> host
|
||||
// Type mismatch between InputIterator and OutputIterator value_types
|
||||
// OutputIterator is a contiguous iterator
|
||||
// value_type of OutputIterator is NOT a boolean type
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline OutputIterator
|
||||
dispatch_copy(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
is_device_iterator<InputIterator>,
|
||||
mpl::not_<
|
||||
is_device_iterator<OutputIterator>
|
||||
>,
|
||||
mpl::not_<
|
||||
is_same_value_type<OutputIterator, InputIterator>
|
||||
>,
|
||||
is_contiguous_iterator<OutputIterator>,
|
||||
mpl::not_<
|
||||
is_bool_value_type<OutputIterator>
|
||||
>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
typedef typename std::iterator_traits<OutputIterator>::value_type output_type;
|
||||
typedef typename InputIterator::value_type input_type;
|
||||
|
||||
const device &device = queue.get_device();
|
||||
|
||||
// loading parameters
|
||||
std::string cache_key =
|
||||
std::string("__boost_compute_copy_to_host_")
|
||||
+ type_name<input_type>() + "_" + type_name<output_type>();
|
||||
boost::shared_ptr<parameter_cache> parameters =
|
||||
detail::parameter_cache::get_global_cache(device);
|
||||
|
||||
size_t map_copy_threshold;
|
||||
size_t direct_copy_threshold;
|
||||
|
||||
// calculate default values of thresholds
|
||||
if (device.type() & device::gpu) {
|
||||
// GPUs
|
||||
map_copy_threshold = 524288; // 0.5 MB
|
||||
direct_copy_threshold = 52428800; // 50 MB
|
||||
}
|
||||
else {
|
||||
// CPUs and other devices
|
||||
map_copy_threshold = 134217728; // 128 MB
|
||||
direct_copy_threshold = 0; // it's never efficient for CPUs
|
||||
}
|
||||
|
||||
// load thresholds
|
||||
map_copy_threshold =
|
||||
parameters->get(
|
||||
cache_key, "map_copy_threshold", map_copy_threshold
|
||||
);
|
||||
direct_copy_threshold =
|
||||
parameters->get(
|
||||
cache_key, "direct_copy_threshold", direct_copy_threshold
|
||||
);
|
||||
|
||||
// select copy method based on thresholds & input_size_bytes
|
||||
size_t count = iterator_range_size(first, last);
|
||||
size_t input_size_bytes = count * sizeof(input_type);
|
||||
|
||||
// [0; map_copy_threshold) -> copy_to_host_map()
|
||||
if(input_size_bytes < map_copy_threshold) {
|
||||
return copy_to_host_map(first, last, result, queue);
|
||||
}
|
||||
// [map_copy_threshold; direct_copy_threshold) -> copy [first;last) to
|
||||
// temporary vector then copy (and convert) to result using std::copy()
|
||||
else if(input_size_bytes < direct_copy_threshold) {
|
||||
std::vector<input_type> vector(count);
|
||||
copy_to_host(first, last, vector.begin(), queue);
|
||||
return std::copy(vector.begin(), vector.end(), result);
|
||||
}
|
||||
|
||||
// [direct_copy_threshold; inf) -> map [result; result + input_size) to
|
||||
// device and run copy kernel on device for copying & casting
|
||||
// map host memory to device.
|
||||
|
||||
// Perform async copy to host, wait for it to be finished and
|
||||
// return the result.
|
||||
// At this point we are sure that count > 1 (first != last), so event
|
||||
// returned by dispatch_copy_async() must be valid.
|
||||
return dispatch_copy_async(first, last, result, queue).get();
|
||||
}
|
||||
|
||||
// device -> device
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline OutputIterator
|
||||
dispatch_copy(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
is_device_iterator<InputIterator>,
|
||||
is_device_iterator<OutputIterator>,
|
||||
mpl::not_<
|
||||
can_copy_with_copy_buffer<
|
||||
InputIterator, OutputIterator
|
||||
>
|
||||
>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
return copy_on_device(first, last, result, queue);
|
||||
}
|
||||
|
||||
// device -> device (specialization for buffer iterators)
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline OutputIterator
|
||||
dispatch_copy(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
is_device_iterator<InputIterator>,
|
||||
is_device_iterator<OutputIterator>,
|
||||
can_copy_with_copy_buffer<
|
||||
InputIterator, OutputIterator
|
||||
>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type value_type;
|
||||
typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
|
||||
|
||||
difference_type n = std::distance(first, last);
|
||||
if(n < 1){
|
||||
// nothing to copy
|
||||
return result;
|
||||
}
|
||||
|
||||
queue.enqueue_copy_buffer(first.get_buffer(),
|
||||
result.get_buffer(),
|
||||
first.get_index() * sizeof(value_type),
|
||||
result.get_index() * sizeof(value_type),
|
||||
static_cast<size_t>(n) * sizeof(value_type));
|
||||
return result + n;
|
||||
}
|
||||
|
||||
// device -> device (async)
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline future<OutputIterator>
|
||||
dispatch_copy_async(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
is_device_iterator<InputIterator>,
|
||||
is_device_iterator<OutputIterator>,
|
||||
mpl::not_<
|
||||
can_copy_with_copy_buffer<
|
||||
InputIterator, OutputIterator
|
||||
>
|
||||
>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
return copy_on_device_async(first, last, result, queue);
|
||||
}
|
||||
|
||||
// device -> device (async, specialization for buffer iterators)
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline future<OutputIterator>
|
||||
dispatch_copy_async(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if<
|
||||
mpl::and_<
|
||||
is_device_iterator<InputIterator>,
|
||||
is_device_iterator<OutputIterator>,
|
||||
can_copy_with_copy_buffer<
|
||||
InputIterator, OutputIterator
|
||||
>
|
||||
>
|
||||
>::type* = 0)
|
||||
{
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type value_type;
|
||||
typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
|
||||
|
||||
difference_type n = std::distance(first, last);
|
||||
if(n < 1){
|
||||
// nothing to copy
|
||||
return make_future(result, event());
|
||||
}
|
||||
|
||||
event event_ =
|
||||
queue.enqueue_copy_buffer(
|
||||
first.get_buffer(),
|
||||
result.get_buffer(),
|
||||
first.get_index() * sizeof(value_type),
|
||||
result.get_index() * sizeof(value_type),
|
||||
static_cast<size_t>(n) * sizeof(value_type)
|
||||
);
|
||||
|
||||
return make_future(result + n, event_);
|
||||
}
|
||||
|
||||
// host -> host
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline OutputIterator
|
||||
dispatch_copy(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue,
|
||||
typename boost::enable_if_c<
|
||||
!is_device_iterator<InputIterator>::value &&
|
||||
!is_device_iterator<OutputIterator>::value
|
||||
>::type* = 0)
|
||||
{
|
||||
(void) queue;
|
||||
|
||||
return std::copy(first, last, result);
|
||||
}
|
||||
|
||||
} // end detail namespace
|
||||
|
||||
/// Copies the values in the range [\p first, \p last) to the range
|
||||
/// beginning at \p result.
|
||||
///
|
||||
/// The generic copy() function can be used for a variety of data
|
||||
/// transfer tasks and provides a standard interface to the following
|
||||
/// OpenCL functions:
|
||||
///
|
||||
/// \li \c clEnqueueReadBuffer()
|
||||
/// \li \c clEnqueueWriteBuffer()
|
||||
/// \li \c clEnqueueCopyBuffer()
|
||||
///
|
||||
/// Unlike the aforementioned OpenCL functions, copy() will also work
|
||||
/// with non-contiguous data-structures (e.g. \c std::list<T>) as
|
||||
/// well as with "fancy" iterators (e.g. transform_iterator).
|
||||
///
|
||||
/// \param first first element in the range to copy
|
||||
/// \param last last element in the range to copy
|
||||
/// \param result first element in the result range
|
||||
/// \param queue command queue to perform the operation
|
||||
///
|
||||
/// \return \c OutputIterator to the end of the result range
|
||||
///
|
||||
/// For example, to copy an array of \c int values on the host to a vector on
|
||||
/// the device:
|
||||
/// \code
|
||||
/// // array on the host
|
||||
/// int data[] = { 1, 2, 3, 4 };
|
||||
///
|
||||
/// // vector on the device
|
||||
/// boost::compute::vector<int> vec(4, context);
|
||||
///
|
||||
/// // copy values to the device vector
|
||||
/// boost::compute::copy(data, data + 4, vec.begin(), queue);
|
||||
/// \endcode
|
||||
///
|
||||
/// The copy algorithm can also be used with standard containers such as
|
||||
/// \c std::vector<T>:
|
||||
/// \code
|
||||
/// std::vector<int> host_vector = ...
|
||||
/// boost::compute::vector<int> device_vector = ...
|
||||
///
|
||||
/// // copy from the host to the device
|
||||
/// boost::compute::copy(
|
||||
/// host_vector.begin(), host_vector.end(), device_vector.begin(), queue
|
||||
/// );
|
||||
///
|
||||
/// // copy from the device to the host
|
||||
/// boost::compute::copy(
|
||||
/// device_vector.begin(), device_vector.end(), host_vector.begin(), queue
|
||||
/// );
|
||||
/// \endcode
|
||||
///
|
||||
/// \see copy_n(), copy_if(), copy_async()
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline OutputIterator copy(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue = system::default_queue())
|
||||
{
|
||||
return detail::dispatch_copy(first, last, result, queue);
|
||||
}
|
||||
|
||||
/// Copies the values in the range [\p first, \p last) to the range
|
||||
/// beginning at \p result. The copy is performed asynchronously.
|
||||
///
|
||||
/// \see copy()
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline future<OutputIterator>
|
||||
copy_async(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
command_queue &queue = system::default_queue())
|
||||
{
|
||||
return detail::dispatch_copy_async(first, last, result, queue);
|
||||
}
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_ALGORITHM_COPY_HPP
|
||||
Reference in New Issue
Block a user