Initial Commit
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
// (C) Copyright 2009-2011 Frederic Bron.
|
||||
//
|
||||
// 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/libs/type_traits for most recent version including documentation.
|
||||
|
||||
#ifndef BOOST_TT_HAS_MINUS_HPP_INCLUDED
|
||||
#define BOOST_TT_HAS_MINUS_HPP_INCLUDED
|
||||
|
||||
#define BOOST_TT_TRAIT_NAME has_minus
|
||||
#define BOOST_TT_TRAIT_OP -
|
||||
#define BOOST_TT_FORBIDDEN_IF\
|
||||
(\
|
||||
/* Lhs==pointer and Rhs==fundamental and Rhs!=integral */\
|
||||
(\
|
||||
::boost::is_pointer< Lhs_noref >::value && \
|
||||
::boost::is_fundamental< Rhs_nocv >::value && \
|
||||
(! ::boost::is_integral< Rhs_noref >::value )\
|
||||
) || \
|
||||
/* Lhs==void* and (Rhs==fundamental or Rhs==pointer) */\
|
||||
(\
|
||||
::boost::is_pointer< Lhs_noref >::value && \
|
||||
::boost::is_void< Lhs_noptr >::value && \
|
||||
( \
|
||||
::boost::is_fundamental< Rhs_nocv >::value || \
|
||||
::boost::is_pointer< Rhs_noref >::value\
|
||||
)\
|
||||
) || \
|
||||
/* Rhs==void* and (Lhs==fundamental or Lhs==pointer) */\
|
||||
(\
|
||||
::boost::is_pointer< Rhs_noref >::value && \
|
||||
::boost::is_void< Rhs_noptr >::value && \
|
||||
(\
|
||||
::boost::is_fundamental< Lhs_nocv >::value || \
|
||||
::boost::is_pointer< Lhs_noref >::value\
|
||||
)\
|
||||
) ||\
|
||||
/* Lhs=fundamental and Rhs=pointer */\
|
||||
(\
|
||||
::boost::is_fundamental< Lhs_nocv >::value && \
|
||||
::boost::is_pointer< Rhs_noref >::value\
|
||||
) ||\
|
||||
/* two different pointers */\
|
||||
(\
|
||||
::boost::is_pointer< Lhs_noref >::value && \
|
||||
::boost::is_pointer< Rhs_noref >::value && \
|
||||
(! ::boost::is_same< Lhs_nocv, Rhs_nocv >::value )\
|
||||
)\
|
||||
)
|
||||
|
||||
|
||||
#include <boost/type_traits/detail/has_binary_operator.hpp>
|
||||
|
||||
#undef BOOST_TT_TRAIT_NAME
|
||||
#undef BOOST_TT_TRAIT_OP
|
||||
#undef BOOST_TT_FORBIDDEN_IF
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2010 John Maddock
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_TYPE_TRAITS_EXT_ADD_LVALUE_REFERENCE__HPP
|
||||
#define BOOST_TYPE_TRAITS_EXT_ADD_LVALUE_REFERENCE__HPP
|
||||
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
template <class T> struct add_lvalue_reference
|
||||
{
|
||||
typedef typename boost::add_reference<T>::type type;
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <class T> struct add_lvalue_reference<T&&>
|
||||
{
|
||||
typedef T& type;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_TYPE_TRAITS_EXT_ADD_LVALUE_REFERENCE__HPP
|
||||
@@ -0,0 +1,635 @@
|
||||
// (C) Copyright John Maddock 2006.
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_MATH_SF_DIGAMMA_HPP
|
||||
#define BOOST_MATH_SF_DIGAMMA_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // Unreachable code (release mode only warning)
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/series.hpp>
|
||||
#include <boost/math/tools/promotion.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/mpl/comparison.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace math{
|
||||
namespace detail{
|
||||
//
|
||||
// Begin by defining the smallest value for which it is safe to
|
||||
// use the asymptotic expansion for digamma:
|
||||
//
|
||||
inline unsigned digamma_large_lim(const mpl::int_<0>*)
|
||||
{ return 20; }
|
||||
inline unsigned digamma_large_lim(const mpl::int_<113>*)
|
||||
{ return 20; }
|
||||
inline unsigned digamma_large_lim(const void*)
|
||||
{ return 10; }
|
||||
//
|
||||
// Implementations of the asymptotic expansion come next,
|
||||
// the coefficients of the series have been evaluated
|
||||
// in advance at high precision, and the series truncated
|
||||
// at the first term that's too small to effect the result.
|
||||
// Note that the series becomes divergent after a while
|
||||
// so truncation is very important.
|
||||
//
|
||||
// This first one gives 34-digit precision for x >= 20:
|
||||
//
|
||||
template <class T>
|
||||
inline T digamma_imp_large(T x, const mpl::int_<113>*)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.003968253968253968253968253968253968253968253968254),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0041666666666666666666666666666666666666666666666667),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0075757575757575757575757575757575757575757575757576),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.021092796092796092796092796092796092796092796092796),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.44325980392156862745098039215686274509803921568627),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.0539543302701197438039543302701197438039543302701),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -26.456212121212121212121212121212121212121212121212),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 281.4601449275362318840579710144927536231884057971),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3607.510546398046398046398046398046398046398046398),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 54827.583333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -974936.82385057471264367816091954022988505747126437),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 20052695.796688078946143462272494530559046688078946),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -472384867.72162990196078431372549019607843137254902),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 12635724795.916666666666666666666666666666666666667)
|
||||
};
|
||||
x -= 1;
|
||||
T result = log(x);
|
||||
result += 1 / (2 * x);
|
||||
T z = 1 / (x*x);
|
||||
result -= z * tools::evaluate_polynomial(P, z);
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// 19-digit precision for x >= 10:
|
||||
//
|
||||
template <class T>
|
||||
inline T digamma_imp_large(T x, const mpl::int_<64>*)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.003968253968253968253968253968253968253968253968254),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0041666666666666666666666666666666666666666666666667),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0075757575757575757575757575757575757575757575757576),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.021092796092796092796092796092796092796092796092796),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.44325980392156862745098039215686274509803921568627),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.0539543302701197438039543302701197438039543302701),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -26.456212121212121212121212121212121212121212121212),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 281.4601449275362318840579710144927536231884057971),
|
||||
};
|
||||
x -= 1;
|
||||
T result = log(x);
|
||||
result += 1 / (2 * x);
|
||||
T z = 1 / (x*x);
|
||||
result -= z * tools::evaluate_polynomial(P, z);
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// 17-digit precision for x >= 10:
|
||||
//
|
||||
template <class T>
|
||||
inline T digamma_imp_large(T x, const mpl::int_<53>*)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.0083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.003968253968253968253968253968253968253968253968254),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.0041666666666666666666666666666666666666666666666667),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.0075757575757575757575757575757575757575757575757576),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.021092796092796092796092796092796092796092796092796),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.44325980392156862745098039215686274509803921568627)
|
||||
};
|
||||
x -= 1;
|
||||
T result = log(x);
|
||||
result += 1 / (2 * x);
|
||||
T z = 1 / (x*x);
|
||||
result -= z * tools::evaluate_polynomial(P, z);
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// 9-digit precision for x >= 10:
|
||||
//
|
||||
template <class T>
|
||||
inline T digamma_imp_large(T x, const mpl::int_<24>*)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 24, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 24, -0.0083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 24, 0.003968253968253968253968253968253968253968253968254)
|
||||
};
|
||||
x -= 1;
|
||||
T result = log(x);
|
||||
result += 1 / (2 * x);
|
||||
T z = 1 / (x*x);
|
||||
result -= z * tools::evaluate_polynomial(P, z);
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// Fully generic asymptotic expansion in terms of Bernoulli numbers, see:
|
||||
// http://functions.wolfram.com/06.14.06.0012.01
|
||||
//
|
||||
template <class T>
|
||||
struct digamma_series_func
|
||||
{
|
||||
private:
|
||||
int k;
|
||||
T xx;
|
||||
T term;
|
||||
public:
|
||||
digamma_series_func(T x) : k(1), xx(x * x), term(1 / (x * x)) {}
|
||||
T operator()()
|
||||
{
|
||||
T result = term * boost::math::bernoulli_b2n<T>(k) / (2 * k);
|
||||
term /= xx;
|
||||
++k;
|
||||
return result;
|
||||
}
|
||||
typedef T result_type;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T digamma_imp_large(T x, const Policy& pol, const mpl::int_<0>*)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
digamma_series_func<T> s(x);
|
||||
T result = log(x) - 1 / (2 * x);
|
||||
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
|
||||
result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, -result);
|
||||
result = -result;
|
||||
policies::check_series_iterations<T>("boost::math::digamma<%1%>(%1%)", max_iter, pol);
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// Now follow rational approximations over the range [1,2].
|
||||
//
|
||||
// 35-digit precision:
|
||||
//
|
||||
template <class T>
|
||||
T digamma_imp_1_2(T x, const mpl::int_<113>*)
|
||||
{
|
||||
//
|
||||
// Now the approximation, we use the form:
|
||||
//
|
||||
// digamma(x) = (x - root) * (Y + R(x-1))
|
||||
//
|
||||
// Where root is the location of the positive root of digamma,
|
||||
// Y is a constant, and R is optimised for low absolute error
|
||||
// compared to Y.
|
||||
//
|
||||
// Max error found at 128-bit long double precision: 5.541e-35
|
||||
// Maximum Deviation Found (approximation error): 1.965e-35
|
||||
//
|
||||
static const float Y = 0.99558162689208984375F;
|
||||
|
||||
static const T root1 = T(1569415565) / 1073741824uL;
|
||||
static const T root2 = (T(381566830) / 1073741824uL) / 1073741824uL;
|
||||
static const T root3 = ((T(111616537) / 1073741824uL) / 1073741824uL) / 1073741824uL;
|
||||
static const T root4 = (((T(503992070) / 1073741824uL) / 1073741824uL) / 1073741824uL) / 1073741824uL;
|
||||
static const T root5 = BOOST_MATH_BIG_CONSTANT(T, 113, 0.52112228569249997894452490385577338504019838794544e-36);
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.25479851061131551526977464225335883769),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.18684290534374944114622235683619897417),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.80360876047931768958995775910991929922),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.67227342794829064330498117008564270136),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.26569010991230617151285010695543858005),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.05775672694575986971640757748003553385),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0071432147823164975485922555833274240665),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00048740753910766168912364555706064993274),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.16454996865214115723416538844975174761e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.20327832297631728077731148515093164955e-6)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.6210924610812025425088411043163287646),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.6850757078559596612621337395886392594),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.4320913706209965531250495490639289418),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.4410872083455009362557012239501953402),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.081385727399251729505165509278152487225),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0089478633066857163432104815183858149496),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00055861622855066424871506755481997374154),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.1760168552357342401304462967950178554e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.20585454493572473724556649516040874384e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.90745971844439990284514121823069162795e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.48857673606545846774761343500033283272e-13),
|
||||
};
|
||||
T g = x - root1;
|
||||
g -= root2;
|
||||
g -= root3;
|
||||
g -= root4;
|
||||
g -= root5;
|
||||
T r = tools::evaluate_polynomial(P, T(x-1)) / tools::evaluate_polynomial(Q, T(x-1));
|
||||
T result = g * Y + g * r;
|
||||
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// 19-digit precision:
|
||||
//
|
||||
template <class T>
|
||||
T digamma_imp_1_2(T x, const mpl::int_<64>*)
|
||||
{
|
||||
//
|
||||
// Now the approximation, we use the form:
|
||||
//
|
||||
// digamma(x) = (x - root) * (Y + R(x-1))
|
||||
//
|
||||
// Where root is the location of the positive root of digamma,
|
||||
// Y is a constant, and R is optimised for low absolute error
|
||||
// compared to Y.
|
||||
//
|
||||
// Max error found at 80-bit long double precision: 5.016e-20
|
||||
// Maximum Deviation Found (approximation error): 3.575e-20
|
||||
//
|
||||
static const float Y = 0.99558162689208984375F;
|
||||
|
||||
static const T root1 = T(1569415565) / 1073741824uL;
|
||||
static const T root2 = (T(381566830) / 1073741824uL) / 1073741824uL;
|
||||
static const T root3 = BOOST_MATH_BIG_CONSTANT(T, 64, 0.9016312093258695918615325266959189453125e-19);
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.254798510611315515235),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.314628554532916496608),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.665836341559876230295),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.314767657147375752913),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0541156266153505273939),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00289268368333918761452)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.1195759927055347547),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.54350554664961128724),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.486986018231042975162),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0660481487173569812846),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00298999662592323990972),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.165079794012604905639e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.317940243105952177571e-7)
|
||||
};
|
||||
T g = x - root1;
|
||||
g -= root2;
|
||||
g -= root3;
|
||||
T r = tools::evaluate_polynomial(P, T(x-1)) / tools::evaluate_polynomial(Q, T(x-1));
|
||||
T result = g * Y + g * r;
|
||||
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// 18-digit precision:
|
||||
//
|
||||
template <class T>
|
||||
T digamma_imp_1_2(T x, const mpl::int_<53>*)
|
||||
{
|
||||
//
|
||||
// Now the approximation, we use the form:
|
||||
//
|
||||
// digamma(x) = (x - root) * (Y + R(x-1))
|
||||
//
|
||||
// Where root is the location of the positive root of digamma,
|
||||
// Y is a constant, and R is optimised for low absolute error
|
||||
// compared to Y.
|
||||
//
|
||||
// Maximum Deviation Found: 1.466e-18
|
||||
// At double precision, max error found: 2.452e-17
|
||||
//
|
||||
static const float Y = 0.99558162689208984F;
|
||||
|
||||
static const T root1 = T(1569415565) / 1073741824uL;
|
||||
static const T root2 = (T(381566830) / 1073741824uL) / 1073741824uL;
|
||||
static const T root3 = BOOST_MATH_BIG_CONSTANT(T, 53, 0.9016312093258695918615325266959189453125e-19);
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.25479851061131551),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.32555031186804491),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.65031853770896507),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.28919126444774784),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.045251321448739056),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.0020713321167745952)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 2.0767117023730469),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 1.4606242909763515),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.43593529692665969),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.054151797245674225),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.0021284987017821144),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.55789841321675513e-6)
|
||||
};
|
||||
T g = x - root1;
|
||||
g -= root2;
|
||||
g -= root3;
|
||||
T r = tools::evaluate_polynomial(P, T(x-1)) / tools::evaluate_polynomial(Q, T(x-1));
|
||||
T result = g * Y + g * r;
|
||||
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// 9-digit precision:
|
||||
//
|
||||
template <class T>
|
||||
inline T digamma_imp_1_2(T x, const mpl::int_<24>*)
|
||||
{
|
||||
//
|
||||
// Now the approximation, we use the form:
|
||||
//
|
||||
// digamma(x) = (x - root) * (Y + R(x-1))
|
||||
//
|
||||
// Where root is the location of the positive root of digamma,
|
||||
// Y is a constant, and R is optimised for low absolute error
|
||||
// compared to Y.
|
||||
//
|
||||
// Maximum Deviation Found: 3.388e-010
|
||||
// At float precision, max error found: 2.008725e-008
|
||||
//
|
||||
static const float Y = 0.99558162689208984f;
|
||||
static const T root = 1532632.0f / 1048576;
|
||||
static const T root_minor = static_cast<T>(0.3700660185912626595423257213284682051735604e-6L);
|
||||
static const T P[] = {
|
||||
0.25479851023250261e0f,
|
||||
-0.44981331915268368e0f,
|
||||
-0.43916936919946835e0f,
|
||||
-0.61041765350579073e-1f
|
||||
};
|
||||
static const T Q[] = {
|
||||
0.1e1,
|
||||
0.15890202430554952e1f,
|
||||
0.65341249856146947e0f,
|
||||
0.63851690523355715e-1f
|
||||
};
|
||||
T g = x - root;
|
||||
g -= root_minor;
|
||||
T r = tools::evaluate_polynomial(P, T(x-1)) / tools::evaluate_polynomial(Q, T(x-1));
|
||||
T result = g * Y + g * r;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Tag, class Policy>
|
||||
T digamma_imp(T x, const Tag* t, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// This handles reflection of negative arguments, and all our
|
||||
// error handling, then forwards to the T-specific approximation.
|
||||
//
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
|
||||
T result = 0;
|
||||
//
|
||||
// Check for negative arguments and use reflection:
|
||||
//
|
||||
if(x <= -1)
|
||||
{
|
||||
// Reflect:
|
||||
x = 1 - x;
|
||||
// Argument reduction for tan:
|
||||
T remainder = x - floor(x);
|
||||
// Shift to negative if > 0.5:
|
||||
if(remainder > 0.5)
|
||||
{
|
||||
remainder -= 1;
|
||||
}
|
||||
//
|
||||
// check for evaluation at a negative pole:
|
||||
//
|
||||
if(remainder == 0)
|
||||
{
|
||||
return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", 0, (1-x), pol);
|
||||
}
|
||||
result = constants::pi<T>() / tan(constants::pi<T>() * remainder);
|
||||
}
|
||||
if(x == 0)
|
||||
return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", 0, x, pol);
|
||||
//
|
||||
// If we're above the lower-limit for the
|
||||
// asymptotic expansion then use it:
|
||||
//
|
||||
if(x >= digamma_large_lim(t))
|
||||
{
|
||||
result += digamma_imp_large(x, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// If x > 2 reduce to the interval [1,2]:
|
||||
//
|
||||
while(x > 2)
|
||||
{
|
||||
x -= 1;
|
||||
result += 1/x;
|
||||
}
|
||||
//
|
||||
// If x < 1 use recurrance to shift to > 1:
|
||||
//
|
||||
while(x < 1)
|
||||
{
|
||||
result -= 1/x;
|
||||
x += 1;
|
||||
}
|
||||
result += digamma_imp_1_2(x, t);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T digamma_imp(T x, const mpl::int_<0>* t, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// This handles reflection of negative arguments, and all our
|
||||
// error handling, then forwards to the T-specific approximation.
|
||||
//
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
|
||||
T result = 0;
|
||||
//
|
||||
// Check for negative arguments and use reflection:
|
||||
//
|
||||
if(x <= -1)
|
||||
{
|
||||
// Reflect:
|
||||
x = 1 - x;
|
||||
// Argument reduction for tan:
|
||||
T remainder = x - floor(x);
|
||||
// Shift to negative if > 0.5:
|
||||
if(remainder > 0.5)
|
||||
{
|
||||
remainder -= 1;
|
||||
}
|
||||
//
|
||||
// check for evaluation at a negative pole:
|
||||
//
|
||||
if(remainder == 0)
|
||||
{
|
||||
return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", 0, (1 - x), pol);
|
||||
}
|
||||
result = constants::pi<T>() / tan(constants::pi<T>() * remainder);
|
||||
}
|
||||
if(x == 0)
|
||||
return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", 0, x, pol);
|
||||
//
|
||||
// If we're above the lower-limit for the
|
||||
// asymptotic expansion then use it, the
|
||||
// limit is a linear interpolation with
|
||||
// limit = 10 at 50 bit precision and
|
||||
// limit = 250 at 1000 bit precision.
|
||||
//
|
||||
int lim = 10 + ((tools::digits<T>() - 50) * 240L) / 950;
|
||||
T two_x = ldexp(x, 1);
|
||||
if(x >= lim)
|
||||
{
|
||||
result += digamma_imp_large(x, pol, t);
|
||||
}
|
||||
else if(floor(x) == x)
|
||||
{
|
||||
//
|
||||
// Special case for integer arguments, see
|
||||
// http://functions.wolfram.com/06.14.03.0001.01
|
||||
//
|
||||
result = -constants::euler<T, Policy>();
|
||||
T val = 1;
|
||||
while(val < x)
|
||||
{
|
||||
result += 1 / val;
|
||||
val += 1;
|
||||
}
|
||||
}
|
||||
else if(floor(two_x) == two_x)
|
||||
{
|
||||
//
|
||||
// Special case for half integer arguments, see:
|
||||
// http://functions.wolfram.com/06.14.03.0007.01
|
||||
//
|
||||
result = -2 * constants::ln_two<T, Policy>() - constants::euler<T, Policy>();
|
||||
int n = itrunc(x);
|
||||
if(n)
|
||||
{
|
||||
for(int k = 1; k < n; ++k)
|
||||
result += 1 / T(k);
|
||||
for(int k = n; k <= 2 * n - 1; ++k)
|
||||
result += 2 / T(k);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Rescale so we can use the asymptotic expansion:
|
||||
//
|
||||
while(x < lim)
|
||||
{
|
||||
result -= 1 / x;
|
||||
x += 1;
|
||||
}
|
||||
result += digamma_imp_large(x, pol, t);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// Initializer: ensure all our constants are initialized prior to the first call of main:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
struct digamma_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
typedef typename policies::precision<T, Policy>::type precision_type;
|
||||
do_init(mpl::bool_<precision_type::value && (precision_type::value <= 113)>());
|
||||
}
|
||||
void do_init(const mpl::true_&)
|
||||
{
|
||||
boost::math::digamma(T(1.5), Policy());
|
||||
boost::math::digamma(T(500), Policy());
|
||||
}
|
||||
void do_init(const mpl::false_&){}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
const typename digamma_initializer<T, Policy>::init digamma_initializer<T, Policy>::initializer;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
digamma(T x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::precision<T, Policy>::type precision_type;
|
||||
typedef typename mpl::if_<
|
||||
mpl::or_<
|
||||
mpl::less_equal<precision_type, mpl::int_<0> >,
|
||||
mpl::greater<precision_type, mpl::int_<114> >
|
||||
>,
|
||||
mpl::int_<0>,
|
||||
typename mpl::if_<
|
||||
mpl::less<precision_type, mpl::int_<25> >,
|
||||
mpl::int_<24>,
|
||||
typename mpl::if_<
|
||||
mpl::less<precision_type, mpl::int_<54> >,
|
||||
mpl::int_<53>,
|
||||
typename mpl::if_<
|
||||
mpl::less<precision_type, mpl::int_<65> >,
|
||||
mpl::int_<64>,
|
||||
mpl::int_<113>
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type tag_type;
|
||||
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
// Force initialization of constants:
|
||||
detail::digamma_initializer<value_type, forwarding_policy>::force_instantiate();
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::digamma_imp(
|
||||
static_cast<value_type>(x),
|
||||
static_cast<const tag_type*>(0), forwarding_policy()), "boost::math::digamma<%1%>(%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
digamma(T x)
|
||||
{
|
||||
return digamma(x, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// (C) Copyright Gennadiy Rozental 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/test for the library home page.
|
||||
//
|
||||
// File : $RCSfile$
|
||||
//
|
||||
// Version : $Revision$
|
||||
//
|
||||
// Description : basic_cstring i/o implementation
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_UTILS_BASIC_CSTRING_IO_HPP
|
||||
#define BOOST_TEST_UTILS_BASIC_CSTRING_IO_HPP
|
||||
|
||||
// Boost.Test
|
||||
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
||||
|
||||
// STL
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace unit_test {
|
||||
|
||||
#ifdef BOOST_CLASSIC_IOSTREAMS
|
||||
|
||||
template<typename CharT>
|
||||
inline std::ostream&
|
||||
operator<<( std::ostream& os, basic_cstring<CharT> const& str )
|
||||
{
|
||||
typedef typename ut_detail::bcs_base_char<CharT>::type char_type;
|
||||
char_type const* const beg = reinterpret_cast<char_type const* const>( str.begin() );
|
||||
char_type const* const end = reinterpret_cast<char_type const* const>( str.end() );
|
||||
os << std::basic_string<char_type>( beg, end - beg );
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<typename CharT1, typename Tr,typename CharT2>
|
||||
inline std::basic_ostream<CharT1,Tr>&
|
||||
operator<<( std::basic_ostream<CharT1,Tr>& os, basic_cstring<CharT2> const& str )
|
||||
{
|
||||
CharT1 const* const beg = reinterpret_cast<CharT1 const*>( str.begin() ); // !!
|
||||
CharT1 const* const end = reinterpret_cast<CharT1 const*>( str.end() );
|
||||
os << std::basic_string<CharT1,Tr>( beg, end - beg );
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_BASIC_CSTRING_IO_HPP_071894GER
|
||||
@@ -0,0 +1,60 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com)
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_ACTOR_INCREMENT_ACTOR_HPP
|
||||
#define BOOST_SPIRIT_ACTOR_INCREMENT_ACTOR_HPP
|
||||
|
||||
#include <boost/spirit/home/classic/namespace.hpp>
|
||||
#include <boost/spirit/home/classic/actor/ref_actor.hpp>
|
||||
|
||||
namespace boost { namespace spirit {
|
||||
|
||||
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Summary:
|
||||
// A semantic action policy that calls the ++ operator on a reference.
|
||||
// (This doc uses convention available in actors.hpp)
|
||||
//
|
||||
// Actions:
|
||||
// ++ref;
|
||||
//
|
||||
// Policy name:
|
||||
// increment_action
|
||||
//
|
||||
// Policy holder, corresponding helper method:
|
||||
// ref_actor, increment_a( ref );
|
||||
//
|
||||
// () operators: both.
|
||||
//
|
||||
// See also ref_actor for more details.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct increment_action
|
||||
{
|
||||
template<
|
||||
typename T
|
||||
>
|
||||
void act(T& ref_) const
|
||||
{
|
||||
++ref_;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// helper method that creates a increment_actor.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template<typename T>
|
||||
inline ref_actor<T,increment_action> increment_a(T& ref_)
|
||||
{
|
||||
return ref_actor<T,increment_action>(ref_);
|
||||
}
|
||||
|
||||
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*=============================================================================
|
||||
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)
|
||||
==============================================================================*/
|
||||
#if !defined(FUSION_EMPTY_10022005_1619)
|
||||
#define FUSION_EMPTY_10022005_1619
|
||||
|
||||
#include <boost/fusion/support/config.hpp>
|
||||
#include <boost/mpl/empty.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic/empty.hpp>
|
||||
|
||||
namespace boost { namespace mpl
|
||||
{
|
||||
template <typename Tag>
|
||||
struct empty_impl;
|
||||
|
||||
template <>
|
||||
struct empty_impl<fusion::fusion_sequence_tag>
|
||||
{
|
||||
template <typename Sequence>
|
||||
struct apply : fusion::result_of::empty<Sequence> {};
|
||||
};
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,134 @@
|
||||
#ifndef BOOST_ARCHIVE_XML_WOARCHIVE_HPP
|
||||
#define BOOST_ARCHIVE_XML_WOARCHIVE_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// xml_woarchive.hpp
|
||||
|
||||
// (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 <boost/config.hpp>
|
||||
#ifdef BOOST_NO_STD_WSTREAMBUF
|
||||
#error "wide char i/o not supported on this platform"
|
||||
#else
|
||||
#include <cstddef> // size_t
|
||||
#if defined(BOOST_NO_STDC_NAMESPACE)
|
||||
namespace std{
|
||||
using ::size_t;
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
#include <ostream>
|
||||
|
||||
//#include <boost/smart_ptr/scoped_ptr.hpp>
|
||||
#include <boost/archive/detail/auto_link_warchive.hpp>
|
||||
#include <boost/archive/basic_text_oprimitive.hpp>
|
||||
#include <boost/archive/basic_xml_oarchive.hpp>
|
||||
#include <boost/archive/detail/register_archive.hpp>
|
||||
#include <boost/serialization/item_version_type.hpp>
|
||||
//#include <boost/archive/detail/utf8_codecvt_facet.hpp>
|
||||
|
||||
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4511 4512)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace archive {
|
||||
|
||||
namespace detail {
|
||||
template<class Archive> class interface_oarchive;
|
||||
} // namespace detail
|
||||
|
||||
template<class Archive>
|
||||
class BOOST_SYMBOL_VISIBLE xml_woarchive_impl :
|
||||
public basic_text_oprimitive<std::wostream>,
|
||||
public basic_xml_oarchive<Archive>
|
||||
{
|
||||
#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
public:
|
||||
#else
|
||||
protected:
|
||||
friend class detail::interface_oarchive<Archive>;
|
||||
friend class basic_xml_oarchive<Archive>;
|
||||
friend class save_access;
|
||||
#endif
|
||||
//void end_preamble(){
|
||||
// basic_xml_oarchive<Archive>::end_preamble();
|
||||
//}
|
||||
template<class T>
|
||||
void
|
||||
save(const T & t){
|
||||
basic_text_oprimitive<std::wostream>::save(t);
|
||||
}
|
||||
void
|
||||
save(const version_type & t){
|
||||
save(static_cast<const unsigned int>(t));
|
||||
}
|
||||
void
|
||||
save(const boost::serialization::item_version_type & t){
|
||||
save(static_cast<const unsigned int>(t));
|
||||
}
|
||||
BOOST_WARCHIVE_DECL void
|
||||
save(const char * t);
|
||||
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
|
||||
BOOST_WARCHIVE_DECL void
|
||||
save(const wchar_t * t);
|
||||
#endif
|
||||
BOOST_WARCHIVE_DECL void
|
||||
save(const std::string &s);
|
||||
#ifndef BOOST_NO_STD_WSTRING
|
||||
BOOST_WARCHIVE_DECL void
|
||||
save(const std::wstring &ws);
|
||||
#endif
|
||||
BOOST_WARCHIVE_DECL
|
||||
xml_woarchive_impl(std::wostream & os, unsigned int flags);
|
||||
BOOST_WARCHIVE_DECL
|
||||
~xml_woarchive_impl();
|
||||
public:
|
||||
BOOST_WARCHIVE_DECL void
|
||||
save_binary(const void *address, std::size_t count);
|
||||
|
||||
};
|
||||
|
||||
// we use the following because we can't use
|
||||
// typedef xml_woarchive_impl<xml_woarchive_impl<...> > xml_woarchive;
|
||||
|
||||
// do not derive from this class. If you want to extend this functionality
|
||||
// via inhertance, derived from xml_woarchive_impl instead. This will
|
||||
// preserve correct static polymorphism.
|
||||
class BOOST_SYMBOL_VISIBLE xml_woarchive :
|
||||
public xml_woarchive_impl<xml_woarchive>
|
||||
{
|
||||
public:
|
||||
xml_woarchive(std::wostream & os, unsigned int flags = 0) :
|
||||
xml_woarchive_impl<xml_woarchive>(os, flags)
|
||||
{}
|
||||
~xml_woarchive(){}
|
||||
};
|
||||
|
||||
} // namespace archive
|
||||
} // namespace boost
|
||||
|
||||
// required by export
|
||||
BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_woarchive)
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
|
||||
|
||||
#endif // BOOST_NO_STD_WSTREAMBUF
|
||||
#endif // BOOST_ARCHIVE_XML_OARCHIVE_HPP
|
||||
@@ -0,0 +1,63 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// 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_PARTITION_COPY_HPP
|
||||
#define BOOST_COMPUTE_ALGORITHM_PARTITION_COPY_HPP
|
||||
|
||||
#include <boost/compute/system.hpp>
|
||||
#include <boost/compute/functional.hpp>
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/algorithm/copy_if.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
/// Copies all of the elements in the range [\p first, \p last) for which
|
||||
/// \p predicate returns \c true to the range beginning at \p first_true
|
||||
/// and all of the elements for which \p predicate returns \c false to
|
||||
/// the range beginning at \p first_false.
|
||||
///
|
||||
/// \see partition()
|
||||
template<class InputIterator,
|
||||
class OutputIterator1,
|
||||
class OutputIterator2,
|
||||
class UnaryPredicate>
|
||||
inline std::pair<OutputIterator1, OutputIterator2>
|
||||
partition_copy(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator1 first_true,
|
||||
OutputIterator2 first_false,
|
||||
UnaryPredicate predicate,
|
||||
command_queue &queue = system::default_queue())
|
||||
{
|
||||
// copy true values
|
||||
OutputIterator1 last_true =
|
||||
::boost::compute::copy_if(first,
|
||||
last,
|
||||
first_true,
|
||||
predicate,
|
||||
queue);
|
||||
|
||||
// copy false values
|
||||
OutputIterator2 last_false =
|
||||
::boost::compute::copy_if(first,
|
||||
last,
|
||||
first_false,
|
||||
not1(predicate),
|
||||
queue);
|
||||
|
||||
// return iterators to the end of the true and the false ranges
|
||||
return std::make_pair(last_true, last_false);
|
||||
}
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_ALGORITHM_PARTITION_COPY_HPP
|
||||
@@ -0,0 +1,365 @@
|
||||
subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,napwid, &
|
||||
lsubtract,nagain,iaptype,mygrid6,bcontest,sync0,f1,xdt,xbase,apsym, &
|
||||
nharderrors,dmin,nbadcrc,ipass,iera,message,xsnr)
|
||||
|
||||
use timer_module, only: timer
|
||||
include 'ft8_params.f90'
|
||||
parameter(NRECENT=10,NP2=2812)
|
||||
character message*22,msgsent*22
|
||||
character*12 recent_calls(NRECENT)
|
||||
character*6 mygrid6
|
||||
logical bcontest
|
||||
real a(5)
|
||||
real s1(0:7,ND),s2(0:7,NN)
|
||||
real ps(0:7)
|
||||
real bmeta(3*ND),bmetap(3*ND)
|
||||
real llr(3*ND),llra(3*ND),llr0(3*ND),llrap(3*ND) !Soft symbols
|
||||
real dd0(15*12000)
|
||||
integer*1 decoded(KK),apmask(3*ND),cw(3*ND)
|
||||
integer*1 msgbits(KK)
|
||||
integer apsym(KK)
|
||||
integer mcq(28),mde(28),mrrr(16),m73(16),mrr73(16)
|
||||
integer itone(NN)
|
||||
integer icos7(0:6),ip(1)
|
||||
integer nappasses(0:5) ! the number of decoding passes to use for each QSO state
|
||||
integer naptypes(0:5,4) ! (nQSOProgress, decoding pass) maximum of 4 passes for now
|
||||
complex cd0(3200)
|
||||
complex ctwk(32)
|
||||
complex csymb(32)
|
||||
logical first,newdat,lsubtract,lapon,nagain
|
||||
data icos7/2,5,6,0,4,1,3/
|
||||
data mcq/1,1,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1/
|
||||
data mrrr/0,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1/
|
||||
data m73/0,1,1,1,1,1,1,0,1,1,0,1,0,0,0,0/
|
||||
data mde/1,1,1,1,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0,1,1,1,0,1,0,0,0,1/
|
||||
data mrr73/0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,1/
|
||||
data first/.true./
|
||||
save nappasses,naptypes
|
||||
|
||||
if(first) then
|
||||
mcq=2*mcq-1
|
||||
mde=2*mde-1
|
||||
mrrr=2*mrrr-1
|
||||
m73=2*m73-1
|
||||
mrr73=2*mrr73-1
|
||||
nappasses(0)=2
|
||||
nappasses(1)=2
|
||||
nappasses(2)=2
|
||||
nappasses(3)=4
|
||||
nappasses(4)=4
|
||||
nappasses(5)=3
|
||||
|
||||
! iaptype
|
||||
!------------------------
|
||||
! 1 CQ ??? ???
|
||||
! 2 MyCall ??? ???
|
||||
! 3 MyCall DxCall ???
|
||||
! 4 MyCall DxCall RRR
|
||||
! 5 MyCall DxCall 73
|
||||
! 6 MyCall DxCall RR73
|
||||
! 7 ??? DxCall ???
|
||||
|
||||
naptypes(0,1:4)=(/1,2,0,0/)
|
||||
naptypes(1,1:4)=(/2,3,0,0/)
|
||||
naptypes(2,1:4)=(/2,3,0,0/)
|
||||
naptypes(3,1:4)=(/3,4,5,6/)
|
||||
naptypes(4,1:4)=(/3,4,5,6/)
|
||||
naptypes(5,1:4)=(/3,1,2,0/) !?
|
||||
first=.false.
|
||||
endif
|
||||
|
||||
max_iterations=30
|
||||
nharderrors=-1
|
||||
fs2=12000.0/NDOWN
|
||||
dt2=1.0/fs2
|
||||
twopi=8.0*atan(1.0)
|
||||
delfbest=0.
|
||||
ibest=0
|
||||
|
||||
call timer('ft8_down',0)
|
||||
call ft8_downsample(dd0,newdat,f1,cd0) !Mix f1 to baseband and downsample
|
||||
call timer('ft8_down',1)
|
||||
|
||||
i0=nint((xdt+0.5)*fs2) !Initial guess for start of signal
|
||||
smax=0.0
|
||||
do idt=i0-8,i0+8 !Search over +/- one quarter symbol
|
||||
call sync8d(cd0,idt,ctwk,0,sync)
|
||||
if(sync.gt.smax) then
|
||||
smax=sync
|
||||
ibest=idt
|
||||
endif
|
||||
enddo
|
||||
xdt2=ibest*dt2 !Improved estimate for DT
|
||||
|
||||
! Now peak up in frequency
|
||||
i0=nint(xdt2*fs2)
|
||||
smax=0.0
|
||||
do ifr=-5,5 !Search over +/- 2.5 Hz
|
||||
delf=ifr*0.5
|
||||
dphi=twopi*delf*dt2
|
||||
phi=0.0
|
||||
do i=1,32
|
||||
ctwk(i)=cmplx(cos(phi),sin(phi))
|
||||
phi=mod(phi+dphi,twopi)
|
||||
enddo
|
||||
call sync8d(cd0,i0,ctwk,1,sync)
|
||||
if( sync .gt. smax ) then
|
||||
smax=sync
|
||||
delfbest=delf
|
||||
endif
|
||||
enddo
|
||||
a=0.0
|
||||
a(1)=-delfbest
|
||||
call twkfreq1(cd0,NP2,fs2,a,cd0)
|
||||
xdt=xdt2
|
||||
f1=f1+delfbest !Improved estimate of DF
|
||||
|
||||
call sync8d(cd0,i0,ctwk,2,sync)
|
||||
|
||||
j=0
|
||||
do k=1,NN
|
||||
i1=ibest+(k-1)*32
|
||||
csymb=cmplx(0.0,0.0)
|
||||
if( i1.ge.1 .and. i1+31 .le. NP2 ) csymb=cd0(i1:i1+31)
|
||||
call four2a(csymb,32,1,-1,1)
|
||||
s2(0:7,k)=abs(csymb(1:8))/1e3
|
||||
enddo
|
||||
|
||||
! sync quality check
|
||||
is1=0
|
||||
is2=0
|
||||
is3=0
|
||||
do k=1,7
|
||||
ip=maxloc(s2(:,k))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is1=is1+1
|
||||
ip=maxloc(s2(:,k+36))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is2=is2+1
|
||||
ip=maxloc(s2(:,k+72))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is3=is3+1
|
||||
enddo
|
||||
! hard sync sum - max is 21
|
||||
nsync=is1+is2+is3
|
||||
if(nsync .le. 6) then ! bail out
|
||||
nbadcrc=1
|
||||
return
|
||||
endif
|
||||
|
||||
j=0
|
||||
do k=1,NN
|
||||
if(k.le.7) cycle
|
||||
if(k.ge.37 .and. k.le.43) cycle
|
||||
if(k.gt.72) cycle
|
||||
j=j+1
|
||||
s1(0:7,j)=s2(0:7,k)
|
||||
enddo
|
||||
|
||||
do j=1,ND
|
||||
i4=3*j-2
|
||||
i2=3*j-1
|
||||
i1=3*j
|
||||
ps=s1(0:7,j)
|
||||
r1=max(ps(1),ps(3),ps(5),ps(7))-max(ps(0),ps(2),ps(4),ps(6))
|
||||
r2=max(ps(2),ps(3),ps(6),ps(7))-max(ps(0),ps(1),ps(4),ps(5))
|
||||
r4=max(ps(4),ps(5),ps(6),ps(7))-max(ps(0),ps(1),ps(2),ps(3))
|
||||
bmeta(i4)=r4
|
||||
bmeta(i2)=r2
|
||||
bmeta(i1)=r1
|
||||
bmetap(i4)=r4
|
||||
bmetap(i2)=r2
|
||||
bmetap(i1)=r1
|
||||
|
||||
if(nQSOProgress .eq. 0 .or. nQSOProgress .eq. 5) then
|
||||
! When bits 88:115 are set as ap bits, bit 115 lives in symbol 39 along
|
||||
! with no-ap bits 116 and 117. Take care of metrics for bits 116 and 117.
|
||||
if(j.eq.39) then ! take care of bits that live in symbol 39
|
||||
if(apsym(28).lt.0) then
|
||||
bmetap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1))
|
||||
bmetap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2))
|
||||
else
|
||||
bmetap(i2)=max(ps(6),ps(7))-max(ps(4),ps(5))
|
||||
bmetap(i1)=max(ps(5),ps(7))-max(ps(4),ps(6))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
! When bits 116:143 are set as ap bits, bit 115 lives in symbol 39 along
|
||||
! with ap bits 116 and 117. Take care of metric for bit 115.
|
||||
! if(j.eq.39) then ! take care of bit 115
|
||||
! iii=2*(apsym(29)+1)/2 + (apsym(30)+1)/2 ! known values of bits 116 & 117
|
||||
! if(iii.eq.0) bmetap(i4)=ps(4)-ps(0)
|
||||
! if(iii.eq.1) bmetap(i4)=ps(5)-ps(1)
|
||||
! if(iii.eq.2) bmetap(i4)=ps(6)-ps(2)
|
||||
! if(iii.eq.3) bmetap(i4)=ps(7)-ps(3)
|
||||
! endif
|
||||
|
||||
! bit 144 lives in symbol 48 and will be 1 if it is set as an ap bit.
|
||||
! take care of metrics for bits 142 and 143
|
||||
if(j.eq.48) then ! bit 144 is always 1
|
||||
bmetap(i4)=max(ps(5),ps(7))-max(ps(1),ps(3))
|
||||
bmetap(i2)=max(ps(3),ps(7))-max(ps(1),ps(5))
|
||||
endif
|
||||
|
||||
! bit 154 lives in symbol 52 and will be 0 if it is set as an ap bit
|
||||
! take care of metrics for bits 155 and 156
|
||||
if(j.eq.52) then ! bit 154 will be 0 if it is set as an ap bit.
|
||||
bmetap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1))
|
||||
bmetap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2))
|
||||
endif
|
||||
|
||||
enddo
|
||||
|
||||
call normalizebmet(bmeta,3*ND)
|
||||
call normalizebmet(bmetap,3*ND)
|
||||
|
||||
ss=0.84
|
||||
llr0=2.0*bmeta/(ss*ss)
|
||||
llra=2.0*bmetap/(ss*ss) ! llr's for use with ap
|
||||
apmag=4.0
|
||||
|
||||
! pass #
|
||||
!------------------------------
|
||||
! 1 regular decoding
|
||||
! 2 erase 24
|
||||
! 3 erase 48
|
||||
! 4 ap pass 1
|
||||
! 5 ap pass 2
|
||||
! 6 ap pass 3
|
||||
! 7 ap pass 4, etc.
|
||||
|
||||
if(lapon) then
|
||||
npasses=3+nappasses(nQSOProgress)
|
||||
else
|
||||
npasses=3
|
||||
endif
|
||||
|
||||
do ipass=1,npasses
|
||||
|
||||
llr=llr0
|
||||
if(ipass.eq.2) llr(1:24)=0.
|
||||
if(ipass.eq.3) llr(1:48)=0.
|
||||
if(ipass.le.3) then
|
||||
apmask=0
|
||||
llrap=llr
|
||||
iaptype=0
|
||||
endif
|
||||
|
||||
if(ipass .gt. 3) then
|
||||
iaptype=naptypes(nQSOProgress,ipass-3)
|
||||
if(iaptype.ge.3 .and. (abs(f1-nfqso).gt.napwid .and. abs(f1-nftx).gt.napwid) ) cycle
|
||||
if(iaptype.eq.1 .or. iaptype.eq.2 ) then ! AP,???,???
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! first 28 bits are AP
|
||||
apmask(144)=1 ! not free text
|
||||
llrap=llr
|
||||
if(iaptype.eq.1) llrap(88:115)=apmag*mcq/ss
|
||||
if(iaptype.eq.2) llrap(88:115)=apmag*apsym(1:28)/ss
|
||||
llrap(116:117)=llra(116:117)
|
||||
llrap(142:143)=llra(142:143)
|
||||
llrap(144)=-apmag/ss
|
||||
endif
|
||||
if(iaptype.eq.3) then ! mycall, dxcall, ???
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! mycall
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(144)=1 ! not free text
|
||||
llrap=llr
|
||||
llrap(88:143)=apmag*apsym(1:56)/ss
|
||||
llrap(144)=-apmag/ss
|
||||
endif
|
||||
if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype.eq.6) then
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! mycall
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(144:159)=1 ! RRR or 73 or RR73
|
||||
llrap=llr
|
||||
llrap(88:143)=apmag*apsym(1:56)/ss
|
||||
if(iaptype.eq.4) llrap(144:159)=apmag*mrrr/ss
|
||||
if(iaptype.eq.5) llrap(144:159)=apmag*m73/ss
|
||||
if(iaptype.eq.6) llrap(144:159)=apmag*mrr73/ss
|
||||
endif
|
||||
if(iaptype.eq.7) then ! ???, dxcall, ???
|
||||
apmask=0
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(144)=1 ! not free text
|
||||
llrap=llr
|
||||
llrap(115)=llra(115)
|
||||
llrap(116:143)=apmag*apsym(29:56)/ss
|
||||
llrap(144)=-apmag/ss
|
||||
endif
|
||||
endif
|
||||
|
||||
cw=0
|
||||
call timer('bpd174 ',0)
|
||||
call bpdecode174(llrap,apmask,max_iterations,decoded,cw,nharderrors, &
|
||||
niterations)
|
||||
call timer('bpd174 ',1)
|
||||
dmin=0.0
|
||||
if(ndepth.eq.3 .and. nharderrors.lt.0) then
|
||||
ndeep=3
|
||||
if(abs(nfqso-f1).le.napwid .or. abs(nftx-f1).le.napwid) then
|
||||
if((ipass.eq.2 .or. ipass.eq.3) .and. .not.nagain) then
|
||||
ndeep=3
|
||||
else
|
||||
ndeep=4
|
||||
endif
|
||||
endif
|
||||
if(nagain) ndeep=5
|
||||
call timer('osd174 ',0)
|
||||
call osd174(llrap,apmask,ndeep,decoded,cw,nharderrors,dmin)
|
||||
call timer('osd174 ',1)
|
||||
endif
|
||||
nbadcrc=1
|
||||
message=' '
|
||||
xsnr=-99.0
|
||||
if(count(cw.eq.0).eq.174) cycle !Reject the all-zero codeword
|
||||
if(any(decoded(73:75).ne.0)) cycle !Reject if any of the 3 extra bits are nonzero
|
||||
if(nharderrors.ge.0 .and. nharderrors+dmin.lt.60.0 .and. &
|
||||
.not.(sync.lt.2.0 .and. nharderrors.gt.35) .and. &
|
||||
.not.(ipass.gt.1 .and. nharderrors.gt.39) .and. &
|
||||
.not.(ipass.eq.3 .and. nharderrors.gt.30) &
|
||||
) then
|
||||
call chkcrc12a(decoded,nbadcrc)
|
||||
else
|
||||
nharderrors=-1
|
||||
cycle
|
||||
endif
|
||||
if(nbadcrc.eq.0) then
|
||||
call extractmessage174(decoded,message,ncrcflag,recent_calls,nrecent)
|
||||
call genft8(message,mygrid6,bcontest,msgsent,msgbits,itone)
|
||||
if(lsubtract) call subtractft8(dd0,itone,f1,xdt2)
|
||||
xsig=0.0
|
||||
xnoi=0.0
|
||||
do i=1,79
|
||||
xsig=xsig+s2(itone(i),i)**2
|
||||
ios=mod(itone(i)+4,7)
|
||||
xnoi=xnoi+s2(ios,i)**2
|
||||
enddo
|
||||
xsnr=0.001
|
||||
if(xnoi.gt.0 .and. xnoi.lt.xsig) xsnr=xsig/xnoi-1.0
|
||||
xsnr=10.0*log10(xsnr)-27.0
|
||||
xsnr2=db(xsig/xbase - 1.0) - 32.0
|
||||
! write(52,3052) f1,xdt,xsig,xnoi,xbase,xsnr,xsnr2
|
||||
!3052 format(7f10.2)
|
||||
if(.not.nagain) xsnr=xsnr2
|
||||
if(xsnr .lt. -24.0) xsnr=-24.0
|
||||
return
|
||||
endif
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine ft8b
|
||||
|
||||
subroutine normalizebmet(bmet,n)
|
||||
real bmet(n)
|
||||
|
||||
bmetav=sum(bmet)/real(n)
|
||||
bmet2av=sum(bmet*bmet)/real(n)
|
||||
var=bmet2av-bmetav*bmetav
|
||||
if( var .gt. 0.0 ) then
|
||||
bmetsig=sqrt(var)
|
||||
else
|
||||
bmetsig=sqrt(bmet2av)
|
||||
endif
|
||||
bmet=bmet/bmetsig
|
||||
return
|
||||
end subroutine normalizebmet
|
||||
@@ -0,0 +1,96 @@
|
||||
=== AP Decoding
|
||||
|
||||
With the QRA64 decoder Nico Palermo, IV3NWV, introduced a technique
|
||||
for decoding with the aid of information that naturally accumulates
|
||||
during a minimal QSO. This _a priori_ (AP) information can be
|
||||
used to increase the sensitivity of the decoder.
|
||||
|
||||
When an operator decides to answer a CQ, he already knows his own
|
||||
callsign and that of his potential QSO partner. He therefore knows
|
||||
what to expect for at least 56 of the 72 message bits in a
|
||||
standard-format response to his call. The _WSJT-X_ decoders for QRA64
|
||||
and FT8 can use these AP bits to decode messages containing them with
|
||||
higher sensitivity than otherwise possible.
|
||||
|
||||
We have implemented AP decoding in slightly different ways in QRA64
|
||||
and FT8. To provide some explicit examples for users, we provide here
|
||||
a brief description of the FT8 behavior.
|
||||
|
||||
The FT8 decoder always tries first to decode a signal without using
|
||||
any AP information. If this attempt fails, and if *Enable AP* is
|
||||
checked on the *Decode* menu, a second attempt hypothesizes that the
|
||||
message contains callsigns MyCall and DxCall. If the QSO has
|
||||
progressed to the point where signal reports have been exchanged, a
|
||||
third attempt hypothesizes that the message contains the known
|
||||
callsigns followed by RRR, RR73, or 73.
|
||||
|
||||
AP decoding attempts effectively set the AP bits to the hypothesized
|
||||
values, as if they had been received perfectly. The decoder then
|
||||
proceeds to determine whether the remaining message and parity bits
|
||||
are consistent with the hypothesized AP bits. If a codeword is found
|
||||
that the decoder judges to have high (but not overwhelmingly high)
|
||||
probability of being correct, a ? character is appended when the
|
||||
decoded message is displayed. Decodes thus marked are not sent to
|
||||
{pskreporter} to avoid occasional misleading spots of false decodes.
|
||||
|
||||
Successful AP decodes are always labeled with an end-of-line indicator
|
||||
of the form aP, where P is one of the single-digit AP decoding types
|
||||
listed in Table 1. For example, an a2 designator says that the
|
||||
successful decode used MyCall as hypothetically known information.
|
||||
|
||||
[[AP_INFO_TABLE]]
|
||||
.AP information types
|
||||
[width="35%",cols="h10,<m20",frame=topbot,options="header"]
|
||||
|===============================================
|
||||
|P | Message components
|
||||
|1 | CQ     ?     ?
|
||||
|2 | MyCall     ?     ?
|
||||
|3 | MyCall DxCall     ?
|
||||
|4 | MyCall DxCall RRR
|
||||
|5 | MyCall DxCall 73
|
||||
|6 | MyCall DxCall RR73
|
||||
|===============================================
|
||||
|
||||
=== Decoded Lines
|
||||
|
||||
Displayed information accompanying decoded messages generally includes UTC,
|
||||
signal-to-noise ratio in dB, time offset DT in seconds, and
|
||||
audio frequency in Hz. Some modes include additional information such
|
||||
as frequency offset from nominal (DF), frequency drift (Drift or F1),
|
||||
or distance (km or mi).
|
||||
|
||||
There may also be some cryptic characters with special meanings
|
||||
summarized in the following Table:
|
||||
|
||||
[[DECODED_LINES_TABLE]]
|
||||
.Notations used on decoded text lines
|
||||
[width="50%",cols="h,3*^",frame=topbot,options="header"]
|
||||
|===========================================
|
||||
|Mode |Mode character|Sync character|End of line information
|
||||
|FT8 | ~ | | ?   aP
|
||||
|JT4 | $ | *, # | f, fN, dNC
|
||||
|JT9 | @ | |
|
||||
|JT65 | # | |
|
||||
|JT65 VHF| # | *, # | f, fN, dNC
|
||||
|QRA64 | : | * | R
|
||||
|ISCAT | | * | M N C T
|
||||
|MSK144 | & | | N H E
|
||||
|===========================================
|
||||
Sync character::
|
||||
`*` - Normal sync +
|
||||
`#` - Alternate sync
|
||||
|
||||
End of line information::
|
||||
`?` - Decoded with lower confidence +
|
||||
`a` - Decoded with aid of some a priori (AP) information +
|
||||
`C` - Confidence indicator [ISCAT and Deep Search; (0-9,*)] +
|
||||
`d` - Deep Search algorithm +
|
||||
`E` - Size of MSK eye diagram opening - if negative, the eye is closed +
|
||||
`f` - Franke-Taylor or Fano algorithm +
|
||||
`H` - Number of bit errors corrected +
|
||||
`M` - Message length (characters) +
|
||||
`N` - Number of Rx intervals or frames averaged +
|
||||
`P` - Number indicating type of AP information (Table 1, above) +
|
||||
`R` - Return code from QRA64 decoder +
|
||||
`T` - Length of analyzed region (s)
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// -----------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2001-2002 Chuck Allison and Jeremy Siek
|
||||
// Copyright (c) 2003-2006, 2008 Gennaro Prota
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// -----------------------------------------------------------
|
||||
|
||||
#ifndef BOOST_DYNAMIC_BITSET_CONFIG_HPP_GP_20040424
|
||||
#define BOOST_DYNAMIC_BITSET_CONFIG_HPP_GP_20040424
|
||||
|
||||
#include "boost/config.hpp"
|
||||
#include "boost/detail/workaround.hpp"
|
||||
|
||||
// support for pre 3.0 libstdc++ - thanks Phil Edwards!
|
||||
#if defined (__STL_CONFIG_H) && !defined (__STL_USE_NEW_IOSTREAMS)
|
||||
# define BOOST_OLD_IOSTREAMS
|
||||
#endif
|
||||
|
||||
// no-op function to workaround gcc bug c++/8419
|
||||
//
|
||||
namespace boost { namespace detail {
|
||||
template <typename T> T make_non_const(T t) { return t; }
|
||||
}}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define BOOST_DYNAMIC_BITSET_WRAP_CONSTANT(expr) \
|
||||
(boost::detail::make_non_const(expr))
|
||||
#else
|
||||
# define BOOST_DYNAMIC_BITSET_WRAP_CONSTANT(expr) (expr)
|
||||
#endif
|
||||
|
||||
//
|
||||
#if (defined __BORLANDC__ && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))) \
|
||||
|| (defined BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
#define BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS
|
||||
#endif
|
||||
|
||||
// if we can't use friends then we simply expose private members
|
||||
//
|
||||
#if defined(BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS)
|
||||
#define BOOST_DYNAMIC_BITSET_PRIVATE public
|
||||
#else
|
||||
#define BOOST_DYNAMIC_BITSET_PRIVATE private
|
||||
#endif
|
||||
|
||||
// A couple of macros to cope with libraries without locale
|
||||
// support. The first macro must be used to declare a reference
|
||||
// to a ctype facet. The second one to widen a char by using
|
||||
// that ctype object. If facets and locales aren't available
|
||||
// the first macro is a no-op and the second one just expands
|
||||
// to its parameter c.
|
||||
//
|
||||
#if defined (BOOST_USE_FACET)
|
||||
|
||||
#define BOOST_DYNAMIC_BITSET_CTYPE_FACET(ch, name, loc) \
|
||||
const std::ctype<ch> & name = \
|
||||
BOOST_USE_FACET(std::ctype<ch>, loc) /**/
|
||||
|
||||
#define BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, c) \
|
||||
(fac.widen(c))
|
||||
#else
|
||||
|
||||
#define BOOST_DYNAMIC_BITSET_CTYPE_FACET(ch, name, loc) /**/
|
||||
#define BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, c) c
|
||||
|
||||
#endif
|
||||
|
||||
#endif // include guard
|
||||
@@ -0,0 +1,360 @@
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <locale.h>
|
||||
#include <fftw3.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QApplication>
|
||||
#include <QRegularExpression>
|
||||
#include <QObject>
|
||||
#include <QSettings>
|
||||
#include <QLibraryInfo>
|
||||
#include <QSysInfo>
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
#include <QStringList>
|
||||
#include <QLockFile>
|
||||
#include <QStack>
|
||||
#include <QSplashScreen>
|
||||
|
||||
#if QT_VERSION >= 0x050200
|
||||
#include <QCommandLineParser>
|
||||
#include <QCommandLineOption>
|
||||
#endif
|
||||
|
||||
#include "revision_utils.hpp"
|
||||
#include "MetaDataRegistry.hpp"
|
||||
#include "SettingsGroup.hpp"
|
||||
#include "TraceFile.hpp"
|
||||
#include "MultiSettings.hpp"
|
||||
#include "mainwindow.h"
|
||||
#include "commons.h"
|
||||
#include "lib/init_random_seed.h"
|
||||
#include "Radio.hpp"
|
||||
#include "FrequencyList.hpp"
|
||||
#include "SplashScreen.hpp"
|
||||
#include "MessageBox.hpp" // last to avoid nasty MS macro definitions
|
||||
|
||||
extern "C" {
|
||||
// Fortran procedures we need
|
||||
void four2a_(_Complex float *, int * nfft, int * ndim, int * isign, int * iform, int len);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct RNGSetup
|
||||
{
|
||||
RNGSetup ()
|
||||
{
|
||||
// one time seed of pseudo RNGs from current time
|
||||
auto seed = QDateTime::currentMSecsSinceEpoch ();
|
||||
qsrand (seed); // this is good for rand() as well
|
||||
}
|
||||
} seeding;
|
||||
|
||||
class MessageTimestamper
|
||||
{
|
||||
public:
|
||||
MessageTimestamper ()
|
||||
{
|
||||
prior_handlers_.push (qInstallMessageHandler (message_handler));
|
||||
}
|
||||
~MessageTimestamper ()
|
||||
{
|
||||
if (prior_handlers_.size ()) qInstallMessageHandler (prior_handlers_.pop ());
|
||||
}
|
||||
|
||||
private:
|
||||
static void message_handler (QtMsgType type, QMessageLogContext const& context, QString const& msg)
|
||||
{
|
||||
QtMessageHandler handler {prior_handlers_.top ()};
|
||||
if (handler)
|
||||
{
|
||||
handler (type, context,
|
||||
QDateTime::currentDateTimeUtc ().toString ("yy-MM-ddTHH:mm:ss.zzzZ: ") + msg);
|
||||
}
|
||||
}
|
||||
static QStack<QtMessageHandler> prior_handlers_;
|
||||
};
|
||||
QStack<QtMessageHandler> MessageTimestamper::prior_handlers_;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// Add timestamps to all debug messages
|
||||
MessageTimestamper message_timestamper;
|
||||
|
||||
init_random_seed ();
|
||||
|
||||
// make the Qt type magic happen
|
||||
Radio::register_types ();
|
||||
register_types ();
|
||||
|
||||
// Multiple instances communicate with jt9 via this
|
||||
QSharedMemory mem_jt9;
|
||||
|
||||
QApplication a(argc, argv);
|
||||
try
|
||||
{
|
||||
setlocale (LC_NUMERIC, "C"); // ensure number forms are in
|
||||
// consistent format, do this after
|
||||
// instantiating QApplication so
|
||||
// that GUI has correct l18n
|
||||
|
||||
// Override programs executable basename as application name.
|
||||
a.setApplicationName ("WSJT-X");
|
||||
a.setApplicationVersion (version ());
|
||||
|
||||
#if QT_VERSION >= 0x050200
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription ("\n" PROJECT_SUMMARY_DESCRIPTION);
|
||||
auto help_option = parser.addHelpOption ();
|
||||
auto version_option = parser.addVersionOption ();
|
||||
|
||||
// support for multiple instances running from a single installation
|
||||
QCommandLineOption rig_option (QStringList {} << "r" << "rig-name"
|
||||
, a.translate ("main", "Where <rig-name> is for multi-instance support.")
|
||||
, a.translate ("main", "rig-name"));
|
||||
parser.addOption (rig_option);
|
||||
|
||||
// support for start up configuration
|
||||
QCommandLineOption cfg_option (QStringList {} << "c" << "config"
|
||||
, a.translate ("main", "Where <configuration> is an existing one.")
|
||||
, a.translate ("main", "configuration"));
|
||||
parser.addOption (cfg_option);
|
||||
|
||||
QCommandLineOption test_option (QStringList {} << "test-mode"
|
||||
, a.translate ("main", "Writable files in test location. Use with caution, for testing only."));
|
||||
parser.addOption (test_option);
|
||||
|
||||
if (!parser.parse (a.arguments ()))
|
||||
{
|
||||
MessageBox::critical_message (nullptr, a.translate ("main", "Command line error"), parser.errorText ());
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parser.isSet (help_option))
|
||||
{
|
||||
MessageBox::information_message (nullptr, a.translate ("main", "Command line help"), parser.helpText ());
|
||||
return 0;
|
||||
}
|
||||
else if (parser.isSet (version_option))
|
||||
{
|
||||
MessageBox::information_message (nullptr, a.translate ("main", "Application version"), a.applicationVersion ());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
QStandardPaths::setTestModeEnabled (parser.isSet (test_option));
|
||||
|
||||
// support for multiple instances running from a single installation
|
||||
bool multiple {false};
|
||||
if (parser.isSet (rig_option) || parser.isSet (test_option))
|
||||
{
|
||||
auto temp_name = parser.value (rig_option);
|
||||
if (!temp_name.isEmpty ())
|
||||
{
|
||||
if (temp_name.contains (QRegularExpression {R"([\\/,])"}))
|
||||
{
|
||||
std::cerr << QObject::tr ("Invalid rig name - \\ & / not allowed").toLocal8Bit ().data () << std::endl;
|
||||
parser.showHelp (-1);
|
||||
}
|
||||
|
||||
a.setApplicationName (a.applicationName () + " - " + temp_name);
|
||||
}
|
||||
|
||||
if (parser.isSet (test_option))
|
||||
{
|
||||
a.setApplicationName (a.applicationName () + " - test");
|
||||
}
|
||||
|
||||
multiple = true;
|
||||
}
|
||||
|
||||
// now we have the application name we can open the settings
|
||||
MultiSettings multi_settings {parser.value (cfg_option)};
|
||||
|
||||
// find the temporary files path
|
||||
QDir temp_dir {QStandardPaths::writableLocation (QStandardPaths::TempLocation)};
|
||||
Q_ASSERT (temp_dir.exists ()); // sanity check
|
||||
|
||||
// disallow multiple instances with same instance key
|
||||
QLockFile instance_lock {temp_dir.absoluteFilePath (a.applicationName () + ".lock")};
|
||||
instance_lock.setStaleLockTime (0);
|
||||
bool lock_ok {false};
|
||||
while (!(lock_ok = instance_lock.tryLock ()))
|
||||
{
|
||||
if (QLockFile::LockFailedError == instance_lock.error ())
|
||||
{
|
||||
auto button = MessageBox::query_message (nullptr
|
||||
, a.translate ("main", "Another instance may be running")
|
||||
, a.translate ("main", "try to remove stale lock file?")
|
||||
, QString {}
|
||||
, MessageBox::Yes | MessageBox::Retry | MessageBox::No
|
||||
, MessageBox::Yes);
|
||||
switch (button)
|
||||
{
|
||||
case MessageBox::Yes:
|
||||
instance_lock.removeStaleLockFile ();
|
||||
break;
|
||||
|
||||
case MessageBox::Retry:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error {"Multiple instances must have unique rig names"};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WSJT_QDEBUG_TO_FILE
|
||||
// Open a trace file
|
||||
TraceFile trace_file {temp_dir.absoluteFilePath (a.applicationName () + "_trace.log")};
|
||||
qDebug () << program_title (revision ()) + " - Program startup";
|
||||
#endif
|
||||
|
||||
// Create a unique writeable temporary directory in a suitable location
|
||||
bool temp_ok {false};
|
||||
QString unique_directory {QApplication::applicationName ()};
|
||||
do
|
||||
{
|
||||
if (!temp_dir.mkpath (unique_directory)
|
||||
|| !temp_dir.cd (unique_directory))
|
||||
{
|
||||
MessageBox::critical_message (nullptr,
|
||||
a.translate ("main", "Failed to create a temporary directory"),
|
||||
a.translate ("main", "Path: \"%1\"").arg (temp_dir.absolutePath ()));
|
||||
throw std::runtime_error {"Failed to create a temporary directory"};
|
||||
}
|
||||
if (!temp_dir.isReadable () || !(temp_ok = QTemporaryFile {temp_dir.absoluteFilePath ("test")}.open ()))
|
||||
{
|
||||
auto button = MessageBox::critical_message (nullptr,
|
||||
a.translate ("main", "Failed to create a usable temporary directory"),
|
||||
a.translate ("main", "Another application may be locking the directory"),
|
||||
a.translate ("main", "Path: \"%1\"").arg (temp_dir.absolutePath ()),
|
||||
MessageBox::Retry | MessageBox::Cancel);
|
||||
if (MessageBox::Cancel == button)
|
||||
{
|
||||
throw std::runtime_error {"Failed to create a usable temporary directory"};
|
||||
}
|
||||
temp_dir.cdUp (); // revert to parent as this one is no good
|
||||
}
|
||||
}
|
||||
while (!temp_ok);
|
||||
|
||||
SplashScreen splash;
|
||||
{
|
||||
// change this key if you want to force a new splash screen
|
||||
// for a new version, the user will be able to re-disable it
|
||||
// if they wish
|
||||
QString splash_flag_name {"Splash_v1.7"};
|
||||
if (multi_settings.common_value (splash_flag_name, true).toBool ())
|
||||
{
|
||||
QObject::connect (&splash, &SplashScreen::disabled, [&, splash_flag_name] {
|
||||
multi_settings.set_common_value (splash_flag_name, false);
|
||||
splash.close ();
|
||||
});
|
||||
splash.show ();
|
||||
a.processEvents ();
|
||||
}
|
||||
}
|
||||
|
||||
int result;
|
||||
do
|
||||
{
|
||||
#if WSJT_QDEBUG_TO_FILE
|
||||
// announce to trace file and dump settings
|
||||
qDebug () << "++++++++++++++++++++++++++++ Settings ++++++++++++++++++++++++++++";
|
||||
for (auto const& key: multi_settings.settings ()->allKeys ())
|
||||
{
|
||||
auto const& value = multi_settings.settings ()->value (key);
|
||||
if (value.canConvert<QVariantList> ())
|
||||
{
|
||||
auto const sequence = value.value<QSequentialIterable> ();
|
||||
qDebug ().nospace () << key << ": ";
|
||||
for (auto const& item: sequence)
|
||||
{
|
||||
qDebug ().nospace () << '\t' << item;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug ().nospace () << key << ": " << value;
|
||||
}
|
||||
}
|
||||
qDebug () << "---------------------------- Settings ----------------------------";
|
||||
#endif
|
||||
|
||||
// Create and initialize shared memory segment
|
||||
// Multiple instances: use rig_name as shared memory key
|
||||
mem_jt9.setKey(a.applicationName ());
|
||||
|
||||
if(!mem_jt9.attach()) {
|
||||
if (!mem_jt9.create(sizeof(struct dec_data))) {
|
||||
splash.hide ();
|
||||
MessageBox::critical_message (nullptr, a.translate ("main", "Shared memory error"),
|
||||
a.translate ("main", "Unable to create shared memory segment"));
|
||||
throw std::runtime_error {"Shared memory error"};
|
||||
}
|
||||
}
|
||||
memset(mem_jt9.data(),0,sizeof(struct dec_data)); //Zero all decoding params in shared memory
|
||||
|
||||
unsigned downSampleFactor;
|
||||
{
|
||||
SettingsGroup {multi_settings.settings (), "Tune"};
|
||||
|
||||
// deal with Windows Vista and earlier input audio rate
|
||||
// converter problems
|
||||
downSampleFactor = multi_settings.settings ()->value ("Audio/DisableInputResampling",
|
||||
#if defined (Q_OS_WIN)
|
||||
// default to true for
|
||||
// Windows Vista and older
|
||||
QSysInfo::WV_VISTA >= QSysInfo::WindowsVersion ? true : false
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
).toBool () ? 1u : 4u;
|
||||
}
|
||||
|
||||
// run the application UI
|
||||
MainWindow w(temp_dir, multiple, &multi_settings, &mem_jt9, downSampleFactor, &splash);
|
||||
w.show();
|
||||
splash.raise ();
|
||||
QObject::connect (&a, SIGNAL (lastWindowClosed()), &a, SLOT (quit()));
|
||||
result = a.exec();
|
||||
}
|
||||
while (!result && !multi_settings.exit ());
|
||||
|
||||
// clean up lazily initialized resources
|
||||
{
|
||||
int nfft {-1};
|
||||
int ndim {1};
|
||||
int isign {1};
|
||||
int iform {1};
|
||||
// free FFT plan resources
|
||||
four2a_ (nullptr, &nfft, &ndim, &isign, &iform, 0);
|
||||
}
|
||||
fftwf_forget_wisdom ();
|
||||
fftwf_cleanup ();
|
||||
|
||||
temp_dir.removeRecursively (); // clean up temp files
|
||||
return result;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
MessageBox::critical_message (nullptr, a.translate ("main", "Fatal error"), e.what ());
|
||||
std::cerr << "Error: " << e.what () << '\n';
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
MessageBox::critical_message (nullptr, a.translate ("main", "Unexpected fatal error"));
|
||||
std::cerr << "Unexpected fatal error\n";
|
||||
throw; // hoping the runtime might tell us more about the exception
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
exit 0
|
||||
@@ -0,0 +1,103 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// 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_DETAIL_SERIAL_SCAN_HPP
|
||||
#define BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_SCAN_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/compute/device.hpp>
|
||||
#include <boost/compute/kernel.hpp>
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/detail/meta_kernel.hpp>
|
||||
#include <boost/compute/detail/iterator_range_size.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
namespace detail {
|
||||
|
||||
template<class InputIterator, class OutputIterator, class T, class BinaryOperator>
|
||||
inline OutputIterator serial_scan(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
bool exclusive,
|
||||
T init,
|
||||
BinaryOperator op,
|
||||
command_queue &queue)
|
||||
{
|
||||
if(first == last){
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef typename
|
||||
std::iterator_traits<InputIterator>::value_type input_type;
|
||||
typedef typename
|
||||
std::iterator_traits<OutputIterator>::value_type output_type;
|
||||
|
||||
const context &context = queue.get_context();
|
||||
|
||||
// create scan kernel
|
||||
meta_kernel k("serial_scan");
|
||||
|
||||
// Arguments
|
||||
size_t n_arg = k.add_arg<ulong_>("n");
|
||||
size_t init_arg = k.add_arg<output_type>("initial_value");
|
||||
|
||||
if(!exclusive){
|
||||
k <<
|
||||
k.decl<const ulong_>("start_idx") << " = 1;\n" <<
|
||||
k.decl<output_type>("sum") << " = " << first[0] << ";\n" <<
|
||||
result[0] << " = sum;\n";
|
||||
}
|
||||
else {
|
||||
k <<
|
||||
k.decl<const ulong_>("start_idx") << " = 0;\n" <<
|
||||
k.decl<output_type>("sum") << " = initial_value;\n";
|
||||
}
|
||||
|
||||
k <<
|
||||
"for(ulong i = start_idx; i < n; i++){\n" <<
|
||||
k.decl<const input_type>("x") << " = "
|
||||
<< first[k.var<ulong_>("i")] << ";\n";
|
||||
|
||||
if(exclusive){
|
||||
k << result[k.var<ulong_>("i")] << " = sum;\n";
|
||||
}
|
||||
|
||||
k << " sum = "
|
||||
<< op(k.var<output_type>("sum"), k.var<output_type>("x"))
|
||||
<< ";\n";
|
||||
|
||||
if(!exclusive){
|
||||
k << result[k.var<ulong_>("i")] << " = sum;\n";
|
||||
}
|
||||
|
||||
k << "}\n";
|
||||
|
||||
// compile scan kernel
|
||||
kernel scan_kernel = k.compile(context);
|
||||
|
||||
// setup kernel arguments
|
||||
size_t n = detail::iterator_range_size(first, last);
|
||||
scan_kernel.set_arg<ulong_>(n_arg, n);
|
||||
scan_kernel.set_arg<output_type>(init_arg, static_cast<output_type>(init));
|
||||
|
||||
// execute the kernel
|
||||
queue.enqueue_1d_range_kernel(scan_kernel, 0, 1, 1);
|
||||
|
||||
// return iterator pointing to the end of the result range
|
||||
return result + n;
|
||||
}
|
||||
|
||||
} // end detail namespace
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_SCAN_HPP
|
||||
@@ -0,0 +1,141 @@
|
||||
|
||||
// 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)
|
||||
//
|
||||
|
||||
// Preprocessed version of "boost/mpl/times.hpp" header
|
||||
// -- DO NOT modify by hand!
|
||||
|
||||
namespace boost { namespace mpl {
|
||||
|
||||
template<
|
||||
typename Tag1
|
||||
, typename Tag2
|
||||
>
|
||||
struct times_impl
|
||||
: if_c<
|
||||
( BOOST_MPL_AUX_NESTED_VALUE_WKND(int, Tag1)
|
||||
> BOOST_MPL_AUX_NESTED_VALUE_WKND(int, Tag2)
|
||||
)
|
||||
|
||||
, aux::cast2nd_impl< times_impl< Tag1,Tag1 >,Tag1, Tag2 >
|
||||
, aux::cast1st_impl< times_impl< Tag2,Tag2 >,Tag1, Tag2 >
|
||||
>::type
|
||||
{
|
||||
};
|
||||
|
||||
/// for Digital Mars C++/compilers with no CTPS/TTP support
|
||||
template<> struct times_impl< na,na >
|
||||
{
|
||||
template< typename U1, typename U2 > struct apply
|
||||
{
|
||||
typedef apply type;
|
||||
BOOST_STATIC_CONSTANT(int, value = 0);
|
||||
};
|
||||
};
|
||||
|
||||
template< typename Tag > struct times_impl< na,Tag >
|
||||
{
|
||||
template< typename U1, typename U2 > struct apply
|
||||
{
|
||||
typedef apply type;
|
||||
BOOST_STATIC_CONSTANT(int, value = 0);
|
||||
};
|
||||
};
|
||||
|
||||
template< typename Tag > struct times_impl< Tag,na >
|
||||
{
|
||||
template< typename U1, typename U2 > struct apply
|
||||
{
|
||||
typedef apply type;
|
||||
BOOST_STATIC_CONSTANT(int, value = 0);
|
||||
};
|
||||
};
|
||||
|
||||
template< typename T > struct times_tag
|
||||
{
|
||||
typedef typename T::tag type;
|
||||
};
|
||||
|
||||
template<
|
||||
typename BOOST_MPL_AUX_NA_PARAM(N1)
|
||||
, typename BOOST_MPL_AUX_NA_PARAM(N2)
|
||||
, typename N3 = na, typename N4 = na, typename N5 = na
|
||||
>
|
||||
struct times
|
||||
: times< times< times< times< N1,N2 >, N3>, N4>, N5>
|
||||
{
|
||||
};
|
||||
|
||||
template<
|
||||
typename N1, typename N2, typename N3, typename N4
|
||||
>
|
||||
struct times< N1,N2,N3,N4,na >
|
||||
|
||||
: times< times< times< N1,N2 >, N3>, N4>
|
||||
{
|
||||
BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(
|
||||
5
|
||||
, times
|
||||
, ( N1, N2, N3, N4, na )
|
||||
)
|
||||
};
|
||||
|
||||
template<
|
||||
typename N1, typename N2, typename N3
|
||||
>
|
||||
struct times< N1,N2,N3,na,na >
|
||||
|
||||
: times< times< N1,N2 >, N3>
|
||||
{
|
||||
BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(
|
||||
5
|
||||
, times
|
||||
, ( N1, N2, N3, na, na )
|
||||
)
|
||||
};
|
||||
|
||||
template<
|
||||
typename N1, typename N2
|
||||
>
|
||||
struct times< N1,N2,na,na,na >
|
||||
: times_impl<
|
||||
typename times_tag<N1>::type
|
||||
, typename times_tag<N2>::type
|
||||
>::template apply< N1,N2 >::type
|
||||
{
|
||||
BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(
|
||||
5
|
||||
, times
|
||||
, ( N1, N2, na, na, na )
|
||||
)
|
||||
|
||||
};
|
||||
|
||||
BOOST_MPL_AUX_NA_SPEC2(2, 5, times)
|
||||
|
||||
}}
|
||||
|
||||
namespace boost { namespace mpl {
|
||||
template<>
|
||||
struct times_impl< integral_c_tag,integral_c_tag >
|
||||
{
|
||||
template< typename N1, typename N2 > struct apply
|
||||
|
||||
: integral_c<
|
||||
typename aux::largest_int<
|
||||
typename N1::value_type
|
||||
, typename N2::value_type
|
||||
>::type
|
||||
, ( BOOST_MPL_AUX_VALUE_WKND(N1)::value
|
||||
* BOOST_MPL_AUX_VALUE_WKND(N2)::value
|
||||
)
|
||||
>
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef BOOST_BIND_ARG_HPP_INCLUDED
|
||||
#define BOOST_BIND_ARG_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// bind/arg.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Distributed under the 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/bind/bind.html for documentation.
|
||||
//
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/is_placeholder.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<bool Eq> struct _arg_eq
|
||||
{
|
||||
};
|
||||
|
||||
template<> struct _arg_eq<true>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template< int I > struct arg
|
||||
{
|
||||
BOOST_CONSTEXPR arg()
|
||||
{
|
||||
}
|
||||
|
||||
template< class T > BOOST_CONSTEXPR arg( T const & /* t */, typename _arg_eq< I == is_placeholder<T>::value >::type * = 0 )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template< int I > BOOST_CONSTEXPR bool operator==( arg<I> const &, arg<I> const & )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
|
||||
|
||||
template< int I > struct is_placeholder< arg<I> >
|
||||
{
|
||||
enum _vt { value = I };
|
||||
};
|
||||
|
||||
template< int I > struct is_placeholder< arg<I> (*) () >
|
||||
{
|
||||
enum _vt { value = I };
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_BIND_ARG_HPP_INCLUDED
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
@@ -0,0 +1,16 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// \file functional.hpp
|
||||
/// Proto callables for various things
|
||||
//
|
||||
// Copyright 2010 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)
|
||||
|
||||
#ifndef BOOST_PROTO_FUNCTIONAL_HPP_EAN_11_27_2010
|
||||
#define BOOST_PROTO_FUNCTIONAL_HPP_EAN_11_27_2010
|
||||
|
||||
#include <boost/proto/functional/std.hpp>
|
||||
#include <boost/proto/functional/fusion.hpp>
|
||||
#include <boost/proto/functional/range.hpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,319 @@
|
||||
// (C) Copyright John Maddock 2001 - 2003.
|
||||
// (C) Copyright David Abrahams 2002 - 2003.
|
||||
// (C) Copyright Aleksey Gurtovoy 2002.
|
||||
// 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.
|
||||
|
||||
// Borland C++ compiler setup:
|
||||
|
||||
//
|
||||
// versions check:
|
||||
// we don't support Borland prior to version 5.4:
|
||||
#if __BORLANDC__ < 0x540
|
||||
# error "Compiler not supported or configured - please reconfigure"
|
||||
#endif
|
||||
|
||||
// last known compiler version:
|
||||
#if (__BORLANDC__ > 0x613)
|
||||
//# if defined(BOOST_ASSERT_CONFIG)
|
||||
# error "Unknown compiler version - please run the configure tests and report the results"
|
||||
//# else
|
||||
//# pragma message( "Unknown compiler version - please run the configure tests and report the results")
|
||||
//# endif
|
||||
#elif (__BORLANDC__ == 0x600)
|
||||
# error "CBuilderX preview compiler is no longer supported"
|
||||
#endif
|
||||
|
||||
//
|
||||
// Support macros to help with standard library detection
|
||||
#if (__BORLANDC__ < 0x560) || defined(_USE_OLD_RW_STL)
|
||||
# define BOOST_BCB_WITH_ROGUE_WAVE
|
||||
#elif __BORLANDC__ < 0x570
|
||||
# define BOOST_BCB_WITH_STLPORT
|
||||
#else
|
||||
# define BOOST_BCB_WITH_DINKUMWARE
|
||||
#endif
|
||||
|
||||
//
|
||||
// Version 5.0 and below:
|
||||
# if __BORLANDC__ <= 0x0550
|
||||
// Borland C++Builder 4 and 5:
|
||||
# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
# if __BORLANDC__ == 0x0550
|
||||
// Borland C++Builder 5, command-line compiler 5.5:
|
||||
# define BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
# endif
|
||||
// Variadic macros do not exist for C++ Builder versions 5 and below
|
||||
#define BOOST_NO_CXX11_VARIADIC_MACROS
|
||||
# endif
|
||||
|
||||
// Version 5.51 and below:
|
||||
#if (__BORLANDC__ <= 0x551)
|
||||
# define BOOST_NO_CV_SPECIALIZATIONS
|
||||
# define BOOST_NO_CV_VOID_SPECIALIZATIONS
|
||||
# define BOOST_NO_DEDUCED_TYPENAME
|
||||
// workaround for missing WCHAR_MAX/WCHAR_MIN:
|
||||
#ifdef __cplusplus
|
||||
#include <climits>
|
||||
#include <cwchar>
|
||||
#else
|
||||
#include <limits.h>
|
||||
#include <wchar.h>
|
||||
#endif // __cplusplus
|
||||
#ifndef WCHAR_MAX
|
||||
# define WCHAR_MAX 0xffff
|
||||
#endif
|
||||
#ifndef WCHAR_MIN
|
||||
# define WCHAR_MIN 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Borland C++ Builder 6 and below:
|
||||
#if (__BORLANDC__ <= 0x564)
|
||||
|
||||
# if defined(NDEBUG) && defined(__cplusplus)
|
||||
// fix broken <cstring> so that Boost.test works:
|
||||
# include <cstring>
|
||||
# undef strcmp
|
||||
# endif
|
||||
// fix broken errno declaration:
|
||||
# include <errno.h>
|
||||
# ifndef errno
|
||||
# define errno errno
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// new bug in 5.61:
|
||||
#if (__BORLANDC__ >= 0x561) && (__BORLANDC__ <= 0x580)
|
||||
// this seems to be needed by the command line compiler, but not the IDE:
|
||||
# define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS
|
||||
#endif
|
||||
|
||||
// Borland C++ Builder 2006 Update 2 and below:
|
||||
#if (__BORLANDC__ <= 0x582)
|
||||
# define BOOST_NO_SFINAE
|
||||
# define BOOST_BCB_PARTIAL_SPECIALIZATION_BUG
|
||||
# define BOOST_NO_TEMPLATE_TEMPLATES
|
||||
|
||||
# define BOOST_NO_PRIVATE_IN_AGGREGATE
|
||||
|
||||
# ifdef _WIN32
|
||||
# define BOOST_NO_SWPRINTF
|
||||
# elif defined(linux) || defined(__linux__) || defined(__linux)
|
||||
// we should really be able to do without this
|
||||
// but the wcs* functions aren't imported into std::
|
||||
# define BOOST_NO_STDC_NAMESPACE
|
||||
// _CPPUNWIND doesn't get automatically set for some reason:
|
||||
# pragma defineonoption BOOST_CPPUNWIND -x
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (__BORLANDC__ <= 0x613) // Beman has asked Alisdair for more info
|
||||
// we shouldn't really need this - but too many things choke
|
||||
// without it, this needs more investigation:
|
||||
# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
# define BOOST_NO_IS_ABSTRACT
|
||||
# define BOOST_NO_FUNCTION_TYPE_SPECIALIZATIONS
|
||||
# define BOOST_NO_USING_TEMPLATE
|
||||
# define BOOST_SP_NO_SP_CONVERTIBLE
|
||||
|
||||
// Temporary workaround
|
||||
#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
|
||||
#endif
|
||||
|
||||
// Borland C++ Builder 2008 and below:
|
||||
# define BOOST_NO_INTEGRAL_INT64_T
|
||||
# define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL
|
||||
# define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS
|
||||
# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
# define BOOST_NO_TWO_PHASE_NAME_LOOKUP
|
||||
# define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE
|
||||
# define BOOST_NO_NESTED_FRIENDSHIP
|
||||
# define BOOST_NO_TYPENAME_WITH_CTOR
|
||||
#if (__BORLANDC__ < 0x600)
|
||||
# define BOOST_ILLEGAL_CV_REFERENCES
|
||||
#endif
|
||||
|
||||
//
|
||||
// Positive Feature detection
|
||||
//
|
||||
// Borland C++ Builder 2008 and below:
|
||||
#if (__BORLANDC__ >= 0x599)
|
||||
# pragma defineonoption BOOST_CODEGEAR_0X_SUPPORT -Ax
|
||||
#endif
|
||||
//
|
||||
// C++0x Macros:
|
||||
//
|
||||
#if !defined( BOOST_CODEGEAR_0X_SUPPORT ) || (__BORLANDC__ < 0x610)
|
||||
# define BOOST_NO_CXX11_CHAR16_T
|
||||
# define BOOST_NO_CXX11_CHAR32_T
|
||||
# define BOOST_NO_CXX11_DECLTYPE
|
||||
# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
|
||||
# define BOOST_NO_CXX11_EXTERN_TEMPLATE
|
||||
# define BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
# define BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
# define BOOST_NO_CXX11_STATIC_ASSERT
|
||||
#else
|
||||
# define BOOST_HAS_ALIGNOF
|
||||
# define BOOST_HAS_CHAR16_T
|
||||
# define BOOST_HAS_CHAR32_T
|
||||
# define BOOST_HAS_DECLTYPE
|
||||
# define BOOST_HAS_EXPLICIT_CONVERSION_OPS
|
||||
# define BOOST_HAS_REF_QUALIFIER
|
||||
# define BOOST_HAS_RVALUE_REFS
|
||||
# define BOOST_HAS_STATIC_ASSERT
|
||||
#endif
|
||||
|
||||
#define BOOST_NO_CXX11_AUTO_DECLARATIONS
|
||||
#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS
|
||||
#define BOOST_NO_CXX11_CONSTEXPR
|
||||
#define BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
|
||||
#define BOOST_NO_CXX11_DELETED_FUNCTIONS
|
||||
#define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
|
||||
#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
|
||||
#define BOOST_NO_CXX11_LAMBDAS
|
||||
#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS
|
||||
#define BOOST_NO_CXX11_NULLPTR
|
||||
#define BOOST_NO_CXX11_RANGE_BASED_FOR
|
||||
#define BOOST_NO_CXX11_RAW_LITERALS
|
||||
#define BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#define BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
#define BOOST_NO_SFINAE_EXPR
|
||||
#define BOOST_NO_CXX11_TEMPLATE_ALIASES
|
||||
#define BOOST_NO_CXX11_UNICODE_LITERALS // UTF-8 still not supported
|
||||
#define BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
#define BOOST_NO_CXX11_NOEXCEPT
|
||||
#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
|
||||
#define BOOST_NO_CXX11_USER_DEFINED_LITERALS
|
||||
#define BOOST_NO_CXX11_ALIGNAS
|
||||
#define BOOST_NO_CXX11_TRAILING_RESULT_TYPES
|
||||
#define BOOST_NO_CXX11_INLINE_NAMESPACES
|
||||
#define BOOST_NO_CXX11_REF_QUALIFIERS
|
||||
#define BOOST_NO_CXX11_FINAL
|
||||
#define BOOST_NO_CXX11_THREAD_LOCAL
|
||||
|
||||
// C++ 14:
|
||||
#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304)
|
||||
# define BOOST_NO_CXX14_AGGREGATE_NSDMI
|
||||
#endif
|
||||
#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304)
|
||||
# define BOOST_NO_CXX14_BINARY_LITERALS
|
||||
#endif
|
||||
#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304)
|
||||
# define BOOST_NO_CXX14_CONSTEXPR
|
||||
#endif
|
||||
#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304)
|
||||
# define BOOST_NO_CXX14_DECLTYPE_AUTO
|
||||
#endif
|
||||
#if (__cplusplus < 201304) // There's no SD6 check for this....
|
||||
# define BOOST_NO_CXX14_DIGIT_SEPARATORS
|
||||
#endif
|
||||
#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304)
|
||||
# define BOOST_NO_CXX14_GENERIC_LAMBDAS
|
||||
#endif
|
||||
#if !defined(__cpp_init_captures) || (__cpp_init_captures < 201304)
|
||||
# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES
|
||||
#endif
|
||||
#if !defined(__cpp_return_type_deduction) || (__cpp_return_type_deduction < 201304)
|
||||
# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION
|
||||
#endif
|
||||
#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304)
|
||||
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
|
||||
#endif
|
||||
|
||||
#if __BORLANDC__ >= 0x590
|
||||
# define BOOST_HAS_TR1_HASH
|
||||
|
||||
# define BOOST_HAS_MACRO_USE_FACET
|
||||
#endif
|
||||
|
||||
//
|
||||
// Post 0x561 we have long long and stdint.h:
|
||||
#if __BORLANDC__ >= 0x561
|
||||
# ifndef __NO_LONG_LONG
|
||||
# define BOOST_HAS_LONG_LONG
|
||||
# else
|
||||
# define BOOST_NO_LONG_LONG
|
||||
# endif
|
||||
// On non-Win32 platforms let the platform config figure this out:
|
||||
# ifdef _WIN32
|
||||
# define BOOST_HAS_STDINT_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Borland C++Builder 6 defaults to using STLPort. If _USE_OLD_RW_STL is
|
||||
// defined, then we have 0x560 or greater with the Rogue Wave implementation
|
||||
// which presumably has the std::DBL_MAX bug.
|
||||
#if defined( BOOST_BCB_WITH_ROGUE_WAVE )
|
||||
// <climits> is partly broken, some macros define symbols that are really in
|
||||
// namespace std, so you end up having to use illegal constructs like
|
||||
// std::DBL_MAX, as a fix we'll just include float.h and have done with:
|
||||
#include <float.h>
|
||||
#endif
|
||||
//
|
||||
// __int64:
|
||||
//
|
||||
#if (__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)
|
||||
# define BOOST_HAS_MS_INT64
|
||||
#endif
|
||||
//
|
||||
// check for exception handling support:
|
||||
//
|
||||
#if !defined(_CPPUNWIND) && !defined(BOOST_CPPUNWIND) && !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS)
|
||||
# define BOOST_NO_EXCEPTIONS
|
||||
#endif
|
||||
//
|
||||
// all versions have a <dirent.h>:
|
||||
//
|
||||
#ifndef __STRICT_ANSI__
|
||||
# define BOOST_HAS_DIRENT_H
|
||||
#endif
|
||||
//
|
||||
// all versions support __declspec:
|
||||
//
|
||||
#if defined(__STRICT_ANSI__)
|
||||
// config/platform/win32.hpp will define BOOST_SYMBOL_EXPORT, etc., unless already defined
|
||||
# define BOOST_SYMBOL_EXPORT
|
||||
#endif
|
||||
//
|
||||
// ABI fixing headers:
|
||||
//
|
||||
#if __BORLANDC__ != 0x600 // not implemented for version 6 compiler yet
|
||||
#ifndef BOOST_ABI_PREFIX
|
||||
# define BOOST_ABI_PREFIX "boost/config/abi/borland_prefix.hpp"
|
||||
#endif
|
||||
#ifndef BOOST_ABI_SUFFIX
|
||||
# define BOOST_ABI_SUFFIX "boost/config/abi/borland_suffix.hpp"
|
||||
#endif
|
||||
#endif
|
||||
//
|
||||
// Disable Win32 support in ANSI mode:
|
||||
//
|
||||
#if __BORLANDC__ < 0x600
|
||||
# pragma defineonoption BOOST_DISABLE_WIN32 -A
|
||||
#elif defined(__STRICT_ANSI__)
|
||||
# define BOOST_DISABLE_WIN32
|
||||
#endif
|
||||
//
|
||||
// MSVC compatibility mode does some nasty things:
|
||||
// TODO: look up if this doesn't apply to the whole 12xx range
|
||||
//
|
||||
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
|
||||
# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
||||
# define BOOST_NO_VOID_RETURNS
|
||||
#endif
|
||||
|
||||
// Borland did not implement value-initialization completely, as I reported
|
||||
// in 2007, Borland Report 51854, "Value-initialization: POD struct should be
|
||||
// zero-initialized", http://qc.embarcadero.com/wc/qcmain.aspx?d=51854
|
||||
// See also: http://www.boost.org/libs/utility/value_init.htm#compiler_issues
|
||||
// (Niels Dekker, LKEB, April 2010)
|
||||
#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION
|
||||
|
||||
#define BOOST_COMPILER "Borland C++ version " BOOST_STRINGIZE(__BORLANDC__)
|
||||
@@ -0,0 +1,16 @@
|
||||
/*=============================================================================
|
||||
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
|
||||
{
|
||||
struct void_;
|
||||
template <
|
||||
typename T0 = void_ , typename T1 = void_ , typename T2 = void_ , typename T3 = void_ , typename T4 = void_ , typename T5 = void_ , typename T6 = void_ , typename T7 = void_ , typename T8 = void_ , typename T9 = void_ , typename T10 = void_ , typename T11 = void_ , typename T12 = void_ , typename T13 = void_ , typename T14 = void_ , typename T15 = void_ , typename T16 = void_ , typename T17 = void_ , typename T18 = void_ , typename T19 = void_ , typename T20 = void_ , typename T21 = void_ , typename T22 = void_ , typename T23 = void_ , typename T24 = void_ , typename T25 = void_ , typename T26 = void_ , typename T27 = void_ , typename T28 = void_ , typename T29 = void_ , typename T30 = void_ , typename T31 = void_ , typename T32 = void_ , typename T33 = void_ , typename T34 = void_ , typename T35 = void_ , typename T36 = void_ , typename T37 = void_ , typename T38 = void_ , typename T39 = void_ , typename T40 = void_ , typename T41 = void_ , typename T42 = void_ , typename T43 = void_ , typename T44 = void_ , typename T45 = void_ , typename T46 = void_ , typename T47 = void_ , typename T48 = void_ , typename T49 = void_
|
||||
>
|
||||
struct list;
|
||||
}}
|
||||
Reference in New Issue
Block a user