Initial Commit

This commit is contained in:
Jordan Sherer
2018-02-08 21:28:33 -05:00
commit 678c1d3966
14352 changed files with 3176737 additions and 0 deletions
@@ -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 youll 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