Initial Commit
This commit is contained in:
@@ -0,0 +1,488 @@
|
||||
// Copyright 2008 Gautam Sewani
|
||||
// Copyright 2008 John Maddock
|
||||
//
|
||||
// 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_DISTRIBUTIONS_DETAIL_HG_PDF_HPP
|
||||
#define BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_PDF_HPP
|
||||
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/special_functions/lanczos.hpp>
|
||||
#include <boost/math/special_functions/gamma.hpp>
|
||||
#include <boost/math/special_functions/pow.hpp>
|
||||
#include <boost/math/special_functions/prime.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Func>
|
||||
void bubble_down_one(T* first, T* last, Func f)
|
||||
{
|
||||
using std::swap;
|
||||
T* next = first;
|
||||
++next;
|
||||
while((next != last) && (!f(*first, *next)))
|
||||
{
|
||||
swap(*first, *next);
|
||||
++first;
|
||||
++next;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct sort_functor
|
||||
{
|
||||
sort_functor(const T* exponents) : m_exponents(exponents){}
|
||||
bool operator()(int i, int j)
|
||||
{
|
||||
return m_exponents[i] > m_exponents[j];
|
||||
}
|
||||
private:
|
||||
const T* m_exponents;
|
||||
};
|
||||
|
||||
template <class T, class Lanczos, class Policy>
|
||||
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const Lanczos&, const Policy&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
BOOST_MATH_INSTRUMENT_FPU
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(x);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(r);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(n);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(N);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(typeid(Lanczos).name());
|
||||
|
||||
T bases[9] = {
|
||||
T(n) + static_cast<T>(Lanczos::g()) + 0.5f,
|
||||
T(r) + static_cast<T>(Lanczos::g()) + 0.5f,
|
||||
T(N - n) + static_cast<T>(Lanczos::g()) + 0.5f,
|
||||
T(N - r) + static_cast<T>(Lanczos::g()) + 0.5f,
|
||||
1 / (T(N) + static_cast<T>(Lanczos::g()) + 0.5f),
|
||||
1 / (T(x) + static_cast<T>(Lanczos::g()) + 0.5f),
|
||||
1 / (T(n - x) + static_cast<T>(Lanczos::g()) + 0.5f),
|
||||
1 / (T(r - x) + static_cast<T>(Lanczos::g()) + 0.5f),
|
||||
1 / (T(N - n - r + x) + static_cast<T>(Lanczos::g()) + 0.5f)
|
||||
};
|
||||
T exponents[9] = {
|
||||
n + T(0.5f),
|
||||
r + T(0.5f),
|
||||
N - n + T(0.5f),
|
||||
N - r + T(0.5f),
|
||||
N + T(0.5f),
|
||||
x + T(0.5f),
|
||||
n - x + T(0.5f),
|
||||
r - x + T(0.5f),
|
||||
N - n - r + x + T(0.5f)
|
||||
};
|
||||
int base_e_factors[9] = {
|
||||
-1, -1, -1, -1, 1, 1, 1, 1, 1
|
||||
};
|
||||
int sorted_indexes[9] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8
|
||||
};
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
BOOST_MATH_INSTRUMENT_FPU
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
std::sort(sorted_indexes, sorted_indexes + 9, sort_functor<T>(exponents));
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
BOOST_MATH_INSTRUMENT_FPU
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
do{
|
||||
exponents[sorted_indexes[0]] -= exponents[sorted_indexes[1]];
|
||||
bases[sorted_indexes[1]] *= bases[sorted_indexes[0]];
|
||||
if((bases[sorted_indexes[1]] < tools::min_value<T>()) && (exponents[sorted_indexes[1]] != 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
base_e_factors[sorted_indexes[1]] += base_e_factors[sorted_indexes[0]];
|
||||
bubble_down_one(sorted_indexes, sorted_indexes + 9, sort_functor<T>(exponents));
|
||||
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
}while(exponents[sorted_indexes[1]] > 1);
|
||||
|
||||
//
|
||||
// Combine equal powers:
|
||||
//
|
||||
int j = 8;
|
||||
while(exponents[sorted_indexes[j]] == 0) --j;
|
||||
while(j)
|
||||
{
|
||||
while(j && (exponents[sorted_indexes[j-1]] == exponents[sorted_indexes[j]]))
|
||||
{
|
||||
bases[sorted_indexes[j-1]] *= bases[sorted_indexes[j]];
|
||||
exponents[sorted_indexes[j]] = 0;
|
||||
base_e_factors[sorted_indexes[j-1]] += base_e_factors[sorted_indexes[j]];
|
||||
bubble_down_one(sorted_indexes + j, sorted_indexes + 9, sort_functor<T>(exponents));
|
||||
--j;
|
||||
}
|
||||
--j;
|
||||
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(j);
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
BOOST_MATH_INSTRUMENT_FPU
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
T result;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[sorted_indexes[0]] * exp(static_cast<T>(base_e_factors[sorted_indexes[0]])));
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[sorted_indexes[0]]);
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
result = pow(bases[sorted_indexes[0]] * exp(static_cast<T>(base_e_factors[sorted_indexes[0]])), exponents[sorted_indexes[0]]);
|
||||
}
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
for(unsigned i = 1; (i < 9) && (exponents[sorted_indexes[i]] > 0); ++i)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
if(result < tools::min_value<T>())
|
||||
return 0; // short circuit further evaluation
|
||||
if(exponents[sorted_indexes[i]] == 1)
|
||||
result *= bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]]));
|
||||
else if(exponents[sorted_indexes[i]] == 0.5f)
|
||||
result *= sqrt(bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]])));
|
||||
else
|
||||
result *= pow(bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]])), exponents[sorted_indexes[i]]);
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
|
||||
result *= Lanczos::lanczos_sum_expG_scaled(static_cast<T>(n + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(r + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - n + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - r + 1))
|
||||
/
|
||||
( Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(x + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(n - x + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(r - x + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - n - r + x + 1)));
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const boost::math::lanczos::undefined_lanczos&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
return exp(
|
||||
boost::math::lgamma(T(n + 1), pol)
|
||||
+ boost::math::lgamma(T(r + 1), pol)
|
||||
+ boost::math::lgamma(T(N - n + 1), pol)
|
||||
+ boost::math::lgamma(T(N - r + 1), pol)
|
||||
- boost::math::lgamma(T(N + 1), pol)
|
||||
- boost::math::lgamma(T(x + 1), pol)
|
||||
- boost::math::lgamma(T(n - x + 1), pol)
|
||||
- boost::math::lgamma(T(r - x + 1), pol)
|
||||
- boost::math::lgamma(T(N - n - r + x + 1), pol));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T integer_power(const T& x, int ex)
|
||||
{
|
||||
if(ex < 0)
|
||||
return 1 / integer_power(x, -ex);
|
||||
switch(ex)
|
||||
{
|
||||
case 0:
|
||||
return 1;
|
||||
case 1:
|
||||
return x;
|
||||
case 2:
|
||||
return x * x;
|
||||
case 3:
|
||||
return x * x * x;
|
||||
case 4:
|
||||
return boost::math::pow<4>(x);
|
||||
case 5:
|
||||
return boost::math::pow<5>(x);
|
||||
case 6:
|
||||
return boost::math::pow<6>(x);
|
||||
case 7:
|
||||
return boost::math::pow<7>(x);
|
||||
case 8:
|
||||
return boost::math::pow<8>(x);
|
||||
}
|
||||
BOOST_MATH_STD_USING
|
||||
#ifdef __SUNPRO_CC
|
||||
return pow(x, T(ex));
|
||||
#else
|
||||
return pow(x, ex);
|
||||
#endif
|
||||
}
|
||||
template <class T>
|
||||
struct hypergeometric_pdf_prime_loop_result_entry
|
||||
{
|
||||
T value;
|
||||
const hypergeometric_pdf_prime_loop_result_entry* next;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4510 4512 4610)
|
||||
#endif
|
||||
|
||||
struct hypergeometric_pdf_prime_loop_data
|
||||
{
|
||||
const unsigned x;
|
||||
const unsigned r;
|
||||
const unsigned n;
|
||||
const unsigned N;
|
||||
unsigned prime_index;
|
||||
unsigned current_prime;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
T hypergeometric_pdf_prime_loop_imp(hypergeometric_pdf_prime_loop_data& data, hypergeometric_pdf_prime_loop_result_entry<T>& result)
|
||||
{
|
||||
while(data.current_prime <= data.N)
|
||||
{
|
||||
unsigned base = data.current_prime;
|
||||
int prime_powers = 0;
|
||||
while(base <= data.N)
|
||||
{
|
||||
prime_powers += data.n / base;
|
||||
prime_powers += data.r / base;
|
||||
prime_powers += (data.N - data.n) / base;
|
||||
prime_powers += (data.N - data.r) / base;
|
||||
prime_powers -= data.N / base;
|
||||
prime_powers -= data.x / base;
|
||||
prime_powers -= (data.n - data.x) / base;
|
||||
prime_powers -= (data.r - data.x) / base;
|
||||
prime_powers -= (data.N - data.n - data.r + data.x) / base;
|
||||
base *= data.current_prime;
|
||||
}
|
||||
if(prime_powers)
|
||||
{
|
||||
T p = integer_power<T>(static_cast<T>(data.current_prime), prime_powers);
|
||||
if((p > 1) && (tools::max_value<T>() / p < result.value))
|
||||
{
|
||||
//
|
||||
// The next calculation would overflow, use recursion
|
||||
// to sidestep the issue:
|
||||
//
|
||||
hypergeometric_pdf_prime_loop_result_entry<T> t = { p, &result };
|
||||
data.current_prime = prime(++data.prime_index);
|
||||
return hypergeometric_pdf_prime_loop_imp<T>(data, t);
|
||||
}
|
||||
if((p < 1) && (tools::min_value<T>() / p > result.value))
|
||||
{
|
||||
//
|
||||
// The next calculation would underflow, use recursion
|
||||
// to sidestep the issue:
|
||||
//
|
||||
hypergeometric_pdf_prime_loop_result_entry<T> t = { p, &result };
|
||||
data.current_prime = prime(++data.prime_index);
|
||||
return hypergeometric_pdf_prime_loop_imp<T>(data, t);
|
||||
}
|
||||
result.value *= p;
|
||||
}
|
||||
data.current_prime = prime(++data.prime_index);
|
||||
}
|
||||
//
|
||||
// When we get to here we have run out of prime factors,
|
||||
// the overall result is the product of all the partial
|
||||
// results we have accumulated on the stack so far, these
|
||||
// are in a linked list starting with "data.head" and ending
|
||||
// with "result".
|
||||
//
|
||||
// All that remains is to multiply them together, taking
|
||||
// care not to overflow or underflow.
|
||||
//
|
||||
// Enumerate partial results >= 1 in variable i
|
||||
// and partial results < 1 in variable j:
|
||||
//
|
||||
hypergeometric_pdf_prime_loop_result_entry<T> const *i, *j;
|
||||
i = &result;
|
||||
while(i && i->value < 1)
|
||||
i = i->next;
|
||||
j = &result;
|
||||
while(j && j->value >= 1)
|
||||
j = j->next;
|
||||
|
||||
T prod = 1;
|
||||
|
||||
while(i || j)
|
||||
{
|
||||
while(i && ((prod <= 1) || (j == 0)))
|
||||
{
|
||||
prod *= i->value;
|
||||
i = i->next;
|
||||
while(i && i->value < 1)
|
||||
i = i->next;
|
||||
}
|
||||
while(j && ((prod >= 1) || (i == 0)))
|
||||
{
|
||||
prod *= j->value;
|
||||
j = j->next;
|
||||
while(j && j->value >= 1)
|
||||
j = j->next;
|
||||
}
|
||||
}
|
||||
|
||||
return prod;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T hypergeometric_pdf_prime_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
|
||||
{
|
||||
hypergeometric_pdf_prime_loop_result_entry<T> result = { 1, 0 };
|
||||
hypergeometric_pdf_prime_loop_data data = { x, r, n, N, 0, prime(0) };
|
||||
return hypergeometric_pdf_prime_loop_imp<T>(data, result);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T hypergeometric_pdf_factorial_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
BOOST_ASSERT(N <= boost::math::max_factorial<T>::value);
|
||||
T result = boost::math::unchecked_factorial<T>(n);
|
||||
T num[3] = {
|
||||
boost::math::unchecked_factorial<T>(r),
|
||||
boost::math::unchecked_factorial<T>(N - n),
|
||||
boost::math::unchecked_factorial<T>(N - r)
|
||||
};
|
||||
T denom[5] = {
|
||||
boost::math::unchecked_factorial<T>(N),
|
||||
boost::math::unchecked_factorial<T>(x),
|
||||
boost::math::unchecked_factorial<T>(n - x),
|
||||
boost::math::unchecked_factorial<T>(r - x),
|
||||
boost::math::unchecked_factorial<T>(N - n - r + x)
|
||||
};
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while((i < 3) || (j < 5))
|
||||
{
|
||||
while((j < 5) && ((result >= 1) || (i >= 3)))
|
||||
{
|
||||
result /= denom[j];
|
||||
++j;
|
||||
}
|
||||
while((i < 3) && ((result <= 1) || (j >= 5)))
|
||||
{
|
||||
result *= num[i];
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
hypergeometric_pdf(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
value_type result;
|
||||
if(N <= boost::math::max_factorial<value_type>::value)
|
||||
{
|
||||
//
|
||||
// If N is small enough then we can evaluate the PDF via the factorials
|
||||
// directly: table lookup of the factorials gives the best performance
|
||||
// of the methods available:
|
||||
//
|
||||
result = detail::hypergeometric_pdf_factorial_imp<value_type>(x, r, n, N, forwarding_policy());
|
||||
}
|
||||
else if(N <= boost::math::prime(boost::math::max_prime - 1))
|
||||
{
|
||||
//
|
||||
// If N is no larger than the largest prime number in our lookup table
|
||||
// (104729) then we can use prime factorisation to evaluate the PDF,
|
||||
// this is slow but accurate:
|
||||
//
|
||||
result = detail::hypergeometric_pdf_prime_imp<value_type>(x, r, n, N, forwarding_policy());
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Catch all case - use the lanczos approximation - where available -
|
||||
// to evaluate the ratio of factorials. This is reasonably fast
|
||||
// (almost as quick as using logarithmic evaluation in terms of lgamma)
|
||||
// but only a few digits better in accuracy than using lgamma:
|
||||
//
|
||||
result = detail::hypergeometric_pdf_lanczos_imp(value_type(), x, r, n, N, evaluation_type(), forwarding_policy());
|
||||
}
|
||||
|
||||
if(result > 1)
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
if(result < 0)
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(result, "boost::math::hypergeometric_pdf<%1%>(%1%,%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/* Boost interval/compare.hpp template implementation file
|
||||
*
|
||||
* Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_NUMERIC_INTERVAL_COMPARE_HPP
|
||||
#define BOOST_NUMERIC_INTERVAL_COMPARE_HPP
|
||||
|
||||
#include <boost/numeric/interval/compare/certain.hpp>
|
||||
#include <boost/numeric/interval/compare/possible.hpp>
|
||||
#include <boost/numeric/interval/compare/explicit.hpp>
|
||||
#include <boost/numeric/interval/compare/lexicographic.hpp>
|
||||
#include <boost/numeric/interval/compare/set.hpp>
|
||||
|
||||
#endif // BOOST_NUMERIC_INTERVAL_COMPARE_HPP
|
||||
@@ -0,0 +1,48 @@
|
||||
// Boost.Units - A C++ library for zero-overhead dimensional analysis and
|
||||
// unit/quantity manipulation and conversion
|
||||
//
|
||||
// Copyright (C) 2003-2008 Matthias Christian Schabel
|
||||
// Copyright (C) 2008 Steven Watanabe
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_UNITS_DETAIL_PUSH_FRONT_IF_HPP
|
||||
#define BOOST_UNITS_DETAIL_PUSH_FRONT_IF_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace units {
|
||||
|
||||
template<class T, class Next>
|
||||
struct list;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<bool>
|
||||
struct push_front_if;
|
||||
|
||||
template<>
|
||||
struct push_front_if<true> {
|
||||
template<class L, class T>
|
||||
struct apply {
|
||||
typedef list<T, L> type;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct push_front_if<false> {
|
||||
template<class L, class T>
|
||||
struct apply {
|
||||
typedef L type;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,132 @@
|
||||
// Boost.Range library
|
||||
//
|
||||
// Copyright Eric Niebler 2014. Use, modification and
|
||||
// distribution is subject to the Boost Software License, Version
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// For more information, see http://www.boost.org/libs/range/
|
||||
//
|
||||
|
||||
#ifndef BOOST_RANGE_DETAIL_MSVC_HAS_ITERATOR_WORKAROUND_HPP
|
||||
#define BOOST_RANGE_DETAIL_MSVC_HAS_ITERATOR_WORKAROUND_HPP
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_RANGE_MUTABLE_ITERATOR_HPP
|
||||
# error This file should only be included from <boost/range/mutable_iterator.hpp>
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1600)
|
||||
namespace boost
|
||||
{
|
||||
namespace cb_details
|
||||
{
|
||||
template <class Buff, class Traits>
|
||||
struct iterator;
|
||||
}
|
||||
|
||||
namespace python
|
||||
{
|
||||
template <class Container
|
||||
, class NextPolicies /*= objects::default_iterator_call_policies*/>
|
||||
struct iterator;
|
||||
}
|
||||
|
||||
namespace type_erasure
|
||||
{
|
||||
template<
|
||||
class Traversal,
|
||||
class T /*= _self*/,
|
||||
class Reference /*= ::boost::use_default*/,
|
||||
class DifferenceType /*= ::std::ptrdiff_t*/,
|
||||
class ValueType /*= typename deduced<iterator_value_type<T> >::type*/
|
||||
>
|
||||
struct iterator;
|
||||
}
|
||||
|
||||
namespace unordered { namespace iterator_detail
|
||||
{
|
||||
template <typename Node>
|
||||
struct iterator;
|
||||
}}
|
||||
|
||||
namespace container { namespace container_detail
|
||||
{
|
||||
template<class IIterator, bool IsConst>
|
||||
class iterator;
|
||||
}}
|
||||
|
||||
namespace spirit { namespace lex { namespace lexertl
|
||||
{
|
||||
template <typename Functor>
|
||||
class iterator;
|
||||
}}}
|
||||
|
||||
namespace range_detail
|
||||
{
|
||||
template <class Buff, class Traits>
|
||||
struct has_iterator< ::boost::cb_details::iterator<Buff, Traits> >
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template <class Buff, class Traits>
|
||||
struct has_iterator< ::boost::cb_details::iterator<Buff, Traits> const>
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template <class Container, class NextPolicies>
|
||||
struct has_iterator< ::boost::python::iterator<Container, NextPolicies> >
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template <class Container, class NextPolicies>
|
||||
struct has_iterator< ::boost::python::iterator<Container, NextPolicies> const>
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template<class Traversal, class T, class Reference, class DifferenceType, class ValueType>
|
||||
struct has_iterator< ::boost::type_erasure::iterator<Traversal, T, Reference, DifferenceType, ValueType> >
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template<class Traversal, class T, class Reference, class DifferenceType, class ValueType>
|
||||
struct has_iterator< ::boost::type_erasure::iterator<Traversal, T, Reference, DifferenceType, ValueType> const>
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template <typename Node>
|
||||
struct has_iterator< ::boost::unordered::iterator_detail::iterator<Node> >
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template <typename Node>
|
||||
struct has_iterator< ::boost::unordered::iterator_detail::iterator<Node> const>
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template<class IIterator, bool IsConst>
|
||||
struct has_iterator< ::boost::container::container_detail::iterator<IIterator, IsConst> >
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template<class IIterator, bool IsConst>
|
||||
struct has_iterator< ::boost::container::container_detail::iterator<IIterator, IsConst> const>
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template <typename Functor>
|
||||
struct has_iterator< ::boost::spirit::lex::lexertl::iterator<Functor> >
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template <typename Functor>
|
||||
struct has_iterator< ::boost::spirit::lex::lexertl::iterator<Functor> const>
|
||||
: mpl::false_
|
||||
{};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,100 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2014 Roshan <thisisroshansmail@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_RANDOM_BERNOULLI_DISTRIBUTION_HPP
|
||||
#define BOOST_COMPUTE_RANDOM_BERNOULLI_DISTRIBUTION_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/function.hpp>
|
||||
#include <boost/compute/types/fundamental.hpp>
|
||||
#include <boost/compute/detail/iterator_range_size.hpp>
|
||||
#include <boost/compute/detail/literal.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
///
|
||||
/// \class bernoulli_distribution
|
||||
/// \brief Produces random boolean values according to the following
|
||||
/// discrete probability function with parameter p :
|
||||
/// P(true/p) = p and P(false/p) = (1 - p)
|
||||
///
|
||||
/// The following example shows how to setup a bernoulli distribution to
|
||||
/// produce random boolean values with parameter p = 0.25
|
||||
///
|
||||
/// \snippet test/test_bernoulli_distribution.cpp generate
|
||||
///
|
||||
template<class RealType = float>
|
||||
class bernoulli_distribution
|
||||
{
|
||||
public:
|
||||
|
||||
/// Creates a new bernoulli distribution
|
||||
bernoulli_distribution(RealType p = 0.5f)
|
||||
: m_p(p)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destroys the bernoulli_distribution object
|
||||
~bernoulli_distribution()
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns the value of the parameter p
|
||||
RealType p() const
|
||||
{
|
||||
return m_p;
|
||||
}
|
||||
|
||||
/// Generates bernoulli distributed booleans and stores
|
||||
/// them in the range [\p first, \p last).
|
||||
template<class OutputIterator, class Generator>
|
||||
void generate(OutputIterator first,
|
||||
OutputIterator last,
|
||||
Generator &generator,
|
||||
command_queue &queue)
|
||||
{
|
||||
size_t count = detail::iterator_range_size(first, last);
|
||||
|
||||
vector<uint_> tmp(count, queue.get_context());
|
||||
generator.generate(tmp.begin(), tmp.end(), queue);
|
||||
|
||||
BOOST_COMPUTE_FUNCTION(bool, scale_random, (const uint_ x),
|
||||
{
|
||||
return (convert_RealType(x) / MAX_RANDOM) < PARAM;
|
||||
});
|
||||
|
||||
scale_random.define("PARAM", detail::make_literal(m_p));
|
||||
scale_random.define("MAX_RANDOM", "UINT_MAX");
|
||||
scale_random.define(
|
||||
"convert_RealType", std::string("convert_") + type_name<RealType>()
|
||||
);
|
||||
|
||||
transform(
|
||||
tmp.begin(), tmp.end(), first, scale_random, queue
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
RealType m_p;
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
boost::is_floating_point<RealType>::value,
|
||||
"Template argument must be a floating point type"
|
||||
);
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_RANDOM_BERNOULLI_DISTRIBUTION_HPP
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "revision_utils.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include "svnversion.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
QString revision_extract_number (QString const& s)
|
||||
{
|
||||
QString revision;
|
||||
|
||||
// try and match a number
|
||||
QRegularExpression re {R"(^[$:]\w+: (\d+[^$]*)\$$)"};
|
||||
auto match = re.match (s);
|
||||
if (match.hasMatch ())
|
||||
{
|
||||
revision = 'r' + match.captured (1);
|
||||
}
|
||||
return revision;
|
||||
}
|
||||
}
|
||||
|
||||
QString revision (QString const& svn_rev_string)
|
||||
{
|
||||
QString result;
|
||||
auto revision_from_svn = revision_extract_number (svn_rev_string);
|
||||
|
||||
#if defined (CMAKE_BUILD)
|
||||
QString svn_info {":Rev: " WSJTX_STRINGIZE (SVNVERSION) " $"};
|
||||
|
||||
auto revision_from_svn_info = revision_extract_number (svn_info);
|
||||
if (!revision_from_svn_info.isEmpty ())
|
||||
{
|
||||
// we managed to get the revision number from svn info etc.
|
||||
result = revision_from_svn_info;
|
||||
}
|
||||
else if (!revision_from_svn.isEmpty ())
|
||||
{
|
||||
// fall back to revision passed in if any
|
||||
result = revision_from_svn;
|
||||
}
|
||||
else
|
||||
{
|
||||
// match anything
|
||||
QRegularExpression re {R"(^[$:]\w+: ([^$]*)\$$)"};
|
||||
auto match = re.match (svn_info);
|
||||
if (match.hasMatch ())
|
||||
{
|
||||
result = match.captured (1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!revision_from_svn.isEmpty ())
|
||||
{
|
||||
// not CMake build so all we have is revision passed
|
||||
result = revision_from_svn;
|
||||
}
|
||||
#endif
|
||||
return result.trimmed ();
|
||||
}
|
||||
|
||||
QString version (bool include_patch)
|
||||
{
|
||||
#if defined (CMAKE_BUILD)
|
||||
QString v {WSJTX_STRINGIZE (WSJTX_VERSION_MAJOR) "." WSJTX_STRINGIZE (WSJTX_VERSION_MINOR)};
|
||||
if (include_patch)
|
||||
{
|
||||
v += "." WSJTX_STRINGIZE (WSJTX_VERSION_PATCH)
|
||||
# if defined (WSJTX_RC)
|
||||
+ "-rc" WSJTX_STRINGIZE (WSJTX_RC)
|
||||
# endif
|
||||
;
|
||||
}
|
||||
#else
|
||||
QString v {"Not for Release"};
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
QString program_title (QString const& revision)
|
||||
{
|
||||
QString id {QCoreApplication::applicationName () + " v" + QCoreApplication::applicationVersion ()};
|
||||
return id + " " + revision + " by K1JT";
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
# /* Copyright (C) 2001
|
||||
# * Housemarque Oy
|
||||
# * http://www.housemarque.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)
|
||||
# */
|
||||
#
|
||||
# /* Revised by Paul Mensonides (2002) */
|
||||
#
|
||||
# /* See http://www.boost.org for most recent version. */
|
||||
#
|
||||
# ifndef BOOST_PREPROCESSOR_ARITHMETIC_DIV_HPP
|
||||
# define BOOST_PREPROCESSOR_ARITHMETIC_DIV_HPP
|
||||
#
|
||||
# include <boost/preprocessor/arithmetic/detail/div_base.hpp>
|
||||
# include <boost/preprocessor/config/config.hpp>
|
||||
# include <boost/preprocessor/tuple/elem.hpp>
|
||||
#
|
||||
# /* BOOST_PP_DIV */
|
||||
#
|
||||
# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
|
||||
# define BOOST_PP_DIV(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE(x, y))
|
||||
# else
|
||||
# define BOOST_PP_DIV(x, y) BOOST_PP_DIV_I(x, y)
|
||||
# define BOOST_PP_DIV_I(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE(x, y))
|
||||
# endif
|
||||
#
|
||||
# /* BOOST_PP_DIV_D */
|
||||
#
|
||||
# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
|
||||
# define BOOST_PP_DIV_D(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE_D(d, x, y))
|
||||
# else
|
||||
# define BOOST_PP_DIV_D(d, x, y) BOOST_PP_DIV_D_I(d, x, y)
|
||||
# define BOOST_PP_DIV_D_I(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE_D(d, x, y))
|
||||
# endif
|
||||
#
|
||||
# endif
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright Neil Groves 2009. Use, modification and
|
||||
// distribution is subject to the Boost Software License, Version
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
//
|
||||
// For more information, see http://www.boost.org/libs/range/
|
||||
//
|
||||
#ifndef BOOST_RANGE_ALGORITHM_REMOVE_HPP_INCLUDED
|
||||
#define BOOST_RANGE_ALGORITHM_REMOVE_HPP_INCLUDED
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/concepts.hpp>
|
||||
#include <boost/range/detail/range_return.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace range
|
||||
{
|
||||
|
||||
/// \brief template function remove
|
||||
///
|
||||
/// range-based version of the remove std algorithm
|
||||
///
|
||||
/// \pre ForwardRange is a model of the ForwardRangeConcept
|
||||
template< class ForwardRange, class Value >
|
||||
inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
|
||||
remove(ForwardRange& rng, const Value& val)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<ForwardRange> ));
|
||||
return std::remove(boost::begin(rng),boost::end(rng),val);
|
||||
}
|
||||
|
||||
/// \overload
|
||||
template< class ForwardRange, class Value >
|
||||
inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
|
||||
remove(const ForwardRange& rng, const Value& val)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<const ForwardRange> ));
|
||||
return std::remove(boost::begin(rng),boost::end(rng),val);
|
||||
}
|
||||
|
||||
// range_return overloads
|
||||
|
||||
/// \overload
|
||||
template< range_return_value re, class ForwardRange, class Value >
|
||||
inline BOOST_DEDUCED_TYPENAME range_return<ForwardRange,re>::type
|
||||
remove(ForwardRange& rng, const Value& val)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<ForwardRange> ));
|
||||
return range_return<ForwardRange,re>::pack(
|
||||
std::remove(boost::begin(rng), boost::end(rng), val),
|
||||
rng);
|
||||
}
|
||||
|
||||
/// \overload
|
||||
template< range_return_value re, class ForwardRange, class Value >
|
||||
inline BOOST_DEDUCED_TYPENAME range_return<const ForwardRange,re>::type
|
||||
remove(const ForwardRange& rng, const Value& val)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<const ForwardRange> ));
|
||||
return range_return<const ForwardRange,re>::pack(
|
||||
std::remove(boost::begin(rng), boost::end(rng), val),
|
||||
rng);
|
||||
}
|
||||
|
||||
} // namespace range
|
||||
using range::remove;
|
||||
} // namespace boost
|
||||
|
||||
#endif // include guard
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
Soft-decision stack-based sequential decoder for K=32 r=1/2
|
||||
convolutional code. This code implements the "stack-bucket" algorithm
|
||||
described in:
|
||||
"Fast Sequential Decoding Algorithm Using a Stack", F. Jelinek
|
||||
|
||||
The ENCODE macro from Phil Karn's (KA9Q) Fano decoder is used.
|
||||
|
||||
Written by Steve Franke, K9AN for WSJT-X (July 2015)
|
||||
*/
|
||||
|
||||
#include "jelinek.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#include "fano.h"
|
||||
|
||||
/* WSPR uses the Layland-Lushbaugh code
|
||||
* Nonsystematic, non-quick look-in, dmin=?, dfree=?
|
||||
*/
|
||||
#define POLY1 0xf2d05351
|
||||
#define POLY2 0xe4613c47
|
||||
|
||||
//Decoder - returns 0 on success, -1 on timeout
|
||||
int jelinek(
|
||||
unsigned int *metric, /* Final path metric (returned value) */
|
||||
unsigned int *cycles, /* Cycle count (returned value) */
|
||||
unsigned char *data, /* Decoded output data */
|
||||
unsigned char *symbols, /* Raw deinterleaved input symbols */
|
||||
unsigned int nbits, /* Number of output bits */
|
||||
unsigned int stacksize,
|
||||
struct snode *stack,
|
||||
int mettab[2][256], /* Metric table, [sent sym][rx symbol] */
|
||||
unsigned int maxcycles)/* Decoding timeout in cycles per bit */
|
||||
{
|
||||
|
||||
// Compute branch metrics for each symbol pair
|
||||
// The sequential decoding algorithm only uses the metrics, not the
|
||||
// symbol values.
|
||||
unsigned int i;
|
||||
long int metrics[81][4];
|
||||
for(i=0; i<nbits; i++){
|
||||
metrics[i][0] = mettab[0][symbols[0]] + mettab[0][symbols[1]];
|
||||
metrics[i][1] = mettab[0][symbols[0]] + mettab[1][symbols[1]];
|
||||
metrics[i][2] = mettab[1][symbols[0]] + mettab[0][symbols[1]];
|
||||
metrics[i][3] = mettab[1][symbols[0]] + mettab[1][symbols[1]];
|
||||
symbols += 2;
|
||||
}
|
||||
|
||||
// zero the stack
|
||||
memset(stack,0,stacksize*sizeof(struct snode));
|
||||
|
||||
// initialize the loop variables
|
||||
unsigned int lsym, ntail=31;
|
||||
uint64_t encstate=0;
|
||||
unsigned int nbuckets=1000;
|
||||
unsigned int low_bucket=nbuckets-1; //will be set on first run-through
|
||||
unsigned int high_bucket=0;
|
||||
unsigned int *buckets, bucket;
|
||||
buckets=malloc(nbuckets*sizeof(unsigned int));
|
||||
memset(buckets,0,nbuckets*sizeof(unsigned int));
|
||||
unsigned int ptr=1;
|
||||
unsigned int stackptr=1; //pointer values of 0 are reserved (they mean that a bucket is empty)
|
||||
unsigned int depth=0, nbits_minus_ntail=nbits-ntail;
|
||||
unsigned int stacksize_minus_1=stacksize-1;
|
||||
long int totmet0, totmet1, gamma=0;
|
||||
|
||||
unsigned int ncycles=maxcycles*nbits;
|
||||
/********************* Start the stack decoder *****************/
|
||||
for (i=1; i <= ncycles; i++) {
|
||||
#ifdef DEBUG
|
||||
printf("***stackptr=%ld, depth=%d, gamma=%d, encstate=%lx, bucket %d, low_bucket %d, high_bucket %d\n",
|
||||
stackptr, depth, gamma, encstate, bucket, low_bucket, high_bucket);
|
||||
#endif
|
||||
// no need to store more than 7 bytes (56 bits) for encoder state because
|
||||
// only 50 bits are not 0's.
|
||||
if( depth < 56 ) {
|
||||
encstate=encstate<<1;
|
||||
ENCODE(lsym,encstate); // get channel symbols associated with the 0 branch
|
||||
} else {
|
||||
ENCODE(lsym,encstate<<(depth-55));
|
||||
}
|
||||
|
||||
// lsym are the 0-branch channel symbols and 3^lsym are the 1-branch
|
||||
// channel symbols (due to a special property of our generator polynomials)
|
||||
totmet0 = gamma+metrics[depth][lsym]; // total metric for 0-branch daughter node
|
||||
totmet1 = gamma+metrics[depth][3^lsym]; // total metric for 1-branch daughter node
|
||||
depth++; //the depth of the daughter nodes
|
||||
|
||||
bucket=(totmet0>>5)+200; //fast, but not particularly safe - totmet can be negative
|
||||
if( bucket > high_bucket ) high_bucket=bucket;
|
||||
if( bucket < low_bucket ) low_bucket=bucket;
|
||||
|
||||
// place the 0 node on the stack, overwriting the parent (current) node
|
||||
stack[ptr].encstate=encstate;
|
||||
stack[ptr].gamma=totmet0;
|
||||
stack[ptr].depth=depth;
|
||||
stack[ptr].jpointer=buckets[bucket];
|
||||
buckets[bucket]=ptr;
|
||||
|
||||
// if in the tail, only need to evaluate the "0" branch.
|
||||
// Otherwise, enter this "if" and place the 1 node on the stack,
|
||||
if( depth <= nbits_minus_ntail ) {
|
||||
if( stackptr < stacksize_minus_1 ) {
|
||||
stackptr++;
|
||||
ptr=stackptr;
|
||||
} else { // stack full
|
||||
while( buckets[low_bucket] == 0 ) { //write latest to where the top of the lowest bucket points
|
||||
low_bucket++;
|
||||
}
|
||||
ptr=buckets[low_bucket];
|
||||
buckets[low_bucket]=stack[ptr].jpointer; //make bucket point to next older entry
|
||||
}
|
||||
|
||||
bucket=(totmet1>>5)+200; //this may not be safe on all compilers
|
||||
if( bucket > high_bucket ) high_bucket=bucket;
|
||||
if( bucket < low_bucket ) low_bucket=bucket;
|
||||
|
||||
stack[ptr].encstate=encstate+1;
|
||||
stack[ptr].gamma=totmet1;
|
||||
stack[ptr].depth=depth;
|
||||
stack[ptr].jpointer=buckets[bucket];
|
||||
buckets[bucket]=ptr;
|
||||
}
|
||||
|
||||
// pick off the latest entry from the high bucket
|
||||
while( buckets[high_bucket] == 0 ) {
|
||||
high_bucket--;
|
||||
}
|
||||
ptr=buckets[high_bucket];
|
||||
buckets[high_bucket]=stack[ptr].jpointer;
|
||||
depth=stack[ptr].depth;
|
||||
gamma=stack[ptr].gamma;
|
||||
encstate=stack[ptr].encstate;
|
||||
|
||||
// we are done if the top entry on the stack is at depth nbits
|
||||
if (depth == nbits) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*cycles = i+1;
|
||||
*metric = gamma; /* Return final path metric */
|
||||
|
||||
// printf("cycles %d stackptr=%d, depth=%d, gamma=%d, encstate=%lx\n",
|
||||
// *cycles, stackptr, depth, *metric, encstate);
|
||||
|
||||
for (i=0; i<7; i++) {
|
||||
data[i]=(encstate>>(48-i*8))&(0x00000000000000ff);
|
||||
}
|
||||
for (i=7; i<11; i++) {
|
||||
data[i]=0;
|
||||
}
|
||||
|
||||
if(*cycles/nbits >= maxcycles) //timed out
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0; //success
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
# /* **************************************************************************
|
||||
# * *
|
||||
# * (C) Copyright Paul Mensonides 2002.
|
||||
# * Distributed under the 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. */
|
||||
#
|
||||
# include <boost/preprocessor/slot/detail/shared.hpp>
|
||||
#
|
||||
# undef BOOST_PP_ITERATION_START_5
|
||||
#
|
||||
# undef BOOST_PP_ITERATION_START_5_DIGIT_1
|
||||
# undef BOOST_PP_ITERATION_START_5_DIGIT_2
|
||||
# undef BOOST_PP_ITERATION_START_5_DIGIT_3
|
||||
# undef BOOST_PP_ITERATION_START_5_DIGIT_4
|
||||
# undef BOOST_PP_ITERATION_START_5_DIGIT_5
|
||||
# undef BOOST_PP_ITERATION_START_5_DIGIT_6
|
||||
# undef BOOST_PP_ITERATION_START_5_DIGIT_7
|
||||
# undef BOOST_PP_ITERATION_START_5_DIGIT_8
|
||||
# undef BOOST_PP_ITERATION_START_5_DIGIT_9
|
||||
# undef BOOST_PP_ITERATION_START_5_DIGIT_10
|
||||
#
|
||||
# if BOOST_PP_SLOT_TEMP_3 == 0
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_3 0
|
||||
# elif BOOST_PP_SLOT_TEMP_3 == 1
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_3 1
|
||||
# elif BOOST_PP_SLOT_TEMP_3 == 2
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_3 2
|
||||
# elif BOOST_PP_SLOT_TEMP_3 == 3
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_3 3
|
||||
# elif BOOST_PP_SLOT_TEMP_3 == 4
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_3 4
|
||||
# elif BOOST_PP_SLOT_TEMP_3 == 5
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_3 5
|
||||
# elif BOOST_PP_SLOT_TEMP_3 == 6
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_3 6
|
||||
# elif BOOST_PP_SLOT_TEMP_3 == 7
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_3 7
|
||||
# elif BOOST_PP_SLOT_TEMP_3 == 8
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_3 8
|
||||
# elif BOOST_PP_SLOT_TEMP_3 == 9
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_3 9
|
||||
# endif
|
||||
#
|
||||
# if BOOST_PP_SLOT_TEMP_2 == 0
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_2 0
|
||||
# elif BOOST_PP_SLOT_TEMP_2 == 1
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_2 1
|
||||
# elif BOOST_PP_SLOT_TEMP_2 == 2
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_2 2
|
||||
# elif BOOST_PP_SLOT_TEMP_2 == 3
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_2 3
|
||||
# elif BOOST_PP_SLOT_TEMP_2 == 4
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_2 4
|
||||
# elif BOOST_PP_SLOT_TEMP_2 == 5
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_2 5
|
||||
# elif BOOST_PP_SLOT_TEMP_2 == 6
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_2 6
|
||||
# elif BOOST_PP_SLOT_TEMP_2 == 7
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_2 7
|
||||
# elif BOOST_PP_SLOT_TEMP_2 == 8
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_2 8
|
||||
# elif BOOST_PP_SLOT_TEMP_2 == 9
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_2 9
|
||||
# endif
|
||||
#
|
||||
# if BOOST_PP_SLOT_TEMP_1 == 0
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_1 0
|
||||
# elif BOOST_PP_SLOT_TEMP_1 == 1
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_1 1
|
||||
# elif BOOST_PP_SLOT_TEMP_1 == 2
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_1 2
|
||||
# elif BOOST_PP_SLOT_TEMP_1 == 3
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_1 3
|
||||
# elif BOOST_PP_SLOT_TEMP_1 == 4
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_1 4
|
||||
# elif BOOST_PP_SLOT_TEMP_1 == 5
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_1 5
|
||||
# elif BOOST_PP_SLOT_TEMP_1 == 6
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_1 6
|
||||
# elif BOOST_PP_SLOT_TEMP_1 == 7
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_1 7
|
||||
# elif BOOST_PP_SLOT_TEMP_1 == 8
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_1 8
|
||||
# elif BOOST_PP_SLOT_TEMP_1 == 9
|
||||
# define BOOST_PP_ITERATION_START_5_DIGIT_1 9
|
||||
# endif
|
||||
#
|
||||
# if BOOST_PP_ITERATION_START_5_DIGIT_3
|
||||
# define BOOST_PP_ITERATION_START_5 BOOST_PP_SLOT_CC_3(BOOST_PP_ITERATION_START_5_DIGIT_3, BOOST_PP_ITERATION_START_5_DIGIT_2, BOOST_PP_ITERATION_START_5_DIGIT_1)
|
||||
# elif BOOST_PP_ITERATION_START_5_DIGIT_2
|
||||
# define BOOST_PP_ITERATION_START_5 BOOST_PP_SLOT_CC_2(BOOST_PP_ITERATION_START_5_DIGIT_2, BOOST_PP_ITERATION_START_5_DIGIT_1)
|
||||
# else
|
||||
# define BOOST_PP_ITERATION_START_5 BOOST_PP_ITERATION_START_5_DIGIT_1
|
||||
# endif
|
||||
@@ -0,0 +1,128 @@
|
||||
// Boost enable_if library
|
||||
|
||||
// Copyright 2003 (c) The Trustees of Indiana University.
|
||||
|
||||
// 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)
|
||||
|
||||
// Authors: Jaakko Jarvi (jajarvi at osl.iu.edu)
|
||||
// Jeremiah Willcock (jewillco at osl.iu.edu)
|
||||
// Andrew Lumsdaine (lums at osl.iu.edu)
|
||||
|
||||
|
||||
#ifndef BOOST_CORE_ENABLE_IF_HPP
|
||||
#define BOOST_CORE_ENABLE_IF_HPP
|
||||
|
||||
#include "boost/config.hpp"
|
||||
|
||||
// Even the definition of enable_if causes problems on some compilers,
|
||||
// so it's macroed out for all compilers that do not support SFINAE
|
||||
|
||||
#ifndef BOOST_NO_SFINAE
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template<typename T, typename R=void>
|
||||
struct enable_if_has_type
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
template <bool B, class T = void>
|
||||
struct enable_if_c {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct enable_if_c<false, T> {};
|
||||
|
||||
template <class Cond, class T = void>
|
||||
struct enable_if : public enable_if_c<Cond::value, T> {};
|
||||
|
||||
template <bool B, class T>
|
||||
struct lazy_enable_if_c {
|
||||
typedef typename T::type type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct lazy_enable_if_c<false, T> {};
|
||||
|
||||
template <class Cond, class T>
|
||||
struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
|
||||
|
||||
|
||||
template <bool B, class T = void>
|
||||
struct disable_if_c {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct disable_if_c<true, T> {};
|
||||
|
||||
template <class Cond, class T = void>
|
||||
struct disable_if : public disable_if_c<Cond::value, T> {};
|
||||
|
||||
template <bool B, class T>
|
||||
struct lazy_disable_if_c {
|
||||
typedef typename T::type type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct lazy_disable_if_c<true, T> {};
|
||||
|
||||
template <class Cond, class T>
|
||||
struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#else
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail { typedef void enable_if_default_T; }
|
||||
|
||||
template <typename T>
|
||||
struct enable_if_does_not_work_on_this_compiler;
|
||||
|
||||
template<typename T, typename R=void>
|
||||
struct enable_if_has_type : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <bool B, class T = detail::enable_if_default_T>
|
||||
struct enable_if_c : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <bool B, class T = detail::enable_if_default_T>
|
||||
struct disable_if_c : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <bool B, class T = detail::enable_if_default_T>
|
||||
struct lazy_enable_if_c : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <bool B, class T = detail::enable_if_default_T>
|
||||
struct lazy_disable_if_c : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <class Cond, class T = detail::enable_if_default_T>
|
||||
struct enable_if : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <class Cond, class T = detail::enable_if_default_T>
|
||||
struct disable_if : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <class Cond, class T = detail::enable_if_default_T>
|
||||
struct lazy_enable_if : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
template <class Cond, class T = detail::enable_if_default_T>
|
||||
struct lazy_disable_if : enable_if_does_not_work_on_this_compiler<T>
|
||||
{ };
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NO_SFINAE
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,156 @@
|
||||
|
||||
// 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/divides.hpp" header
|
||||
// -- DO NOT modify by hand!
|
||||
|
||||
namespace boost { namespace mpl {
|
||||
|
||||
template<
|
||||
typename Tag1
|
||||
, typename Tag2
|
||||
>
|
||||
struct divides_impl
|
||||
: if_c<
|
||||
( BOOST_MPL_AUX_NESTED_VALUE_WKND(int, Tag1)
|
||||
> BOOST_MPL_AUX_NESTED_VALUE_WKND(int, Tag2)
|
||||
)
|
||||
|
||||
, aux::cast2nd_impl< divides_impl< Tag1,Tag1 >,Tag1, Tag2 >
|
||||
, aux::cast1st_impl< divides_impl< Tag2,Tag2 >,Tag1, Tag2 >
|
||||
>::type
|
||||
{
|
||||
};
|
||||
|
||||
/// for Digital Mars C++/compilers with no CTPS/TTP support
|
||||
template<> struct divides_impl< na,na >
|
||||
{
|
||||
template< typename U1, typename U2 > struct apply
|
||||
{
|
||||
typedef apply type;
|
||||
BOOST_STATIC_CONSTANT(int, value = 0);
|
||||
};
|
||||
};
|
||||
|
||||
template< typename Tag > struct divides_impl< na,Tag >
|
||||
{
|
||||
template< typename U1, typename U2 > struct apply
|
||||
{
|
||||
typedef apply type;
|
||||
BOOST_STATIC_CONSTANT(int, value = 0);
|
||||
};
|
||||
};
|
||||
|
||||
template< typename Tag > struct divides_impl< Tag,na >
|
||||
{
|
||||
template< typename U1, typename U2 > struct apply
|
||||
{
|
||||
typedef apply type;
|
||||
BOOST_STATIC_CONSTANT(int, value = 0);
|
||||
};
|
||||
};
|
||||
|
||||
template< typename T > struct divides_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 divides
|
||||
: divides< divides< divides< divides< N1,N2 >, N3>, N4>, N5>
|
||||
{
|
||||
BOOST_MPL_AUX_LAMBDA_SUPPORT(
|
||||
5
|
||||
, divides
|
||||
, ( N1, N2, N3, N4, N5 )
|
||||
)
|
||||
};
|
||||
|
||||
template<
|
||||
typename N1, typename N2, typename N3, typename N4
|
||||
>
|
||||
struct divides< N1,N2,N3,N4,na >
|
||||
|
||||
: divides< divides< divides< N1,N2 >, N3>, N4>
|
||||
{
|
||||
BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(
|
||||
5
|
||||
, divides
|
||||
, ( N1, N2, N3, N4, na )
|
||||
)
|
||||
};
|
||||
|
||||
template<
|
||||
typename N1, typename N2, typename N3
|
||||
>
|
||||
struct divides< N1,N2,N3,na,na >
|
||||
|
||||
: divides< divides< N1,N2 >, N3>
|
||||
{
|
||||
BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(
|
||||
5
|
||||
, divides
|
||||
, ( N1, N2, N3, na, na )
|
||||
)
|
||||
};
|
||||
|
||||
template<
|
||||
typename N1, typename N2
|
||||
>
|
||||
struct divides< N1,N2,na,na,na >
|
||||
: divides_impl<
|
||||
typename divides_tag<N1>::type
|
||||
, typename divides_tag<N2>::type
|
||||
>::template apply< N1,N2 >::type
|
||||
{
|
||||
BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(
|
||||
5
|
||||
, divides
|
||||
, ( N1, N2, na, na, na )
|
||||
)
|
||||
|
||||
};
|
||||
|
||||
BOOST_MPL_AUX_NA_SPEC2(2, 5, divides)
|
||||
|
||||
}}
|
||||
|
||||
namespace boost { namespace mpl {
|
||||
|
||||
namespace aux {
|
||||
template< typename T, T n1, T n2 >
|
||||
struct divides_wknd
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(T, value = (n1 / n2));
|
||||
typedef integral_c< T,value > type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
struct divides_impl< integral_c_tag,integral_c_tag >
|
||||
{
|
||||
template< typename N1, typename N2 > struct apply
|
||||
: aux::divides_wknd<
|
||||
typename aux::largest_int<
|
||||
typename N1::value_type
|
||||
, typename N2::value_type
|
||||
>::type
|
||||
, N1::value
|
||||
, N2::value
|
||||
>::type
|
||||
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
}}
|
||||
Binary file not shown.
@@ -0,0 +1,24 @@
|
||||
|
||||
#ifndef BOOST_MPL_O1_SIZE_FWD_HPP_INCLUDED
|
||||
#define BOOST_MPL_O1_SIZE_FWD_HPP_INCLUDED
|
||||
|
||||
// Copyright Aleksey Gurtovoy 2000-2004
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/mpl for documentation.
|
||||
|
||||
// $Id$
|
||||
// $Date$
|
||||
// $Revision$
|
||||
|
||||
namespace boost { namespace mpl {
|
||||
|
||||
template< typename Tag > struct O1_size_impl;
|
||||
template< typename Sequence > struct O1_size;
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_MPL_O1_SIZE_FWD_HPP_INCLUDED
|
||||
@@ -0,0 +1,32 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2005-2006 Dan Marsden
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_FUSION_EMPTY_IMPL_31122005_1554)
|
||||
#define BOOST_FUSION_EMPTY_IMPL_31122005_1554
|
||||
|
||||
#include <boost/fusion/support/config.hpp>
|
||||
#include <boost/mpl/empty.hpp>
|
||||
|
||||
namespace boost { namespace fusion
|
||||
{
|
||||
struct mpl_sequence_tag;
|
||||
|
||||
namespace extension
|
||||
{
|
||||
template <typename Sequence>
|
||||
struct empty_impl;
|
||||
|
||||
template <>
|
||||
struct empty_impl<mpl_sequence_tag>
|
||||
{
|
||||
template <typename Sequence>
|
||||
struct apply : mpl::empty<Sequence> {};
|
||||
};
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,22 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
This is an auto-generated file. Do not edit!
|
||||
==============================================================================*/
|
||||
|
||||
#if FUSION_MAX_MAP_SIZE <= 10
|
||||
#include <boost/fusion/container/generation/detail/preprocessed/map_tie10.hpp>
|
||||
#elif FUSION_MAX_MAP_SIZE <= 20
|
||||
#include <boost/fusion/container/generation/detail/preprocessed/map_tie20.hpp>
|
||||
#elif FUSION_MAX_MAP_SIZE <= 30
|
||||
#include <boost/fusion/container/generation/detail/preprocessed/map_tie30.hpp>
|
||||
#elif FUSION_MAX_MAP_SIZE <= 40
|
||||
#include <boost/fusion/container/generation/detail/preprocessed/map_tie40.hpp>
|
||||
#elif FUSION_MAX_MAP_SIZE <= 50
|
||||
#include <boost/fusion/container/generation/detail/preprocessed/map_tie50.hpp>
|
||||
#else
|
||||
#error "FUSION_MAX_MAP_SIZE out of bounds for preprocessed headers"
|
||||
#endif
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* Copyright (c) 2014 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file atomic/detail/ops_extending_cas_based.hpp
|
||||
*
|
||||
* This header contains a boilerplate of the \c operations template implementation that requires sign/zero extension in arithmetic operations.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_OPS_EXTENDING_CAS_BASED_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_DETAIL_OPS_EXTENDING_CAS_BASED_HPP_INCLUDED_
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/storage_type.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
template< typename Base, std::size_t Size, bool Signed >
|
||||
struct extending_cas_based_operations :
|
||||
public Base
|
||||
{
|
||||
typedef typename Base::storage_type storage_type;
|
||||
typedef typename make_storage_type< Size, Signed >::type emulated_storage_type;
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_val;
|
||||
atomics::detail::non_atomic_load(storage, old_val);
|
||||
emulated_storage_type new_val;
|
||||
do
|
||||
{
|
||||
new_val = static_cast< emulated_storage_type >(old_val) + static_cast< emulated_storage_type >(v);
|
||||
}
|
||||
while (!Base::compare_exchange_weak(storage, old_val, static_cast< storage_type >(new_val), order, memory_order_relaxed));
|
||||
return old_val;
|
||||
}
|
||||
|
||||
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
||||
{
|
||||
storage_type old_val;
|
||||
atomics::detail::non_atomic_load(storage, old_val);
|
||||
emulated_storage_type new_val;
|
||||
do
|
||||
{
|
||||
new_val = static_cast< emulated_storage_type >(old_val) - static_cast< emulated_storage_type >(v);
|
||||
}
|
||||
while (!Base::compare_exchange_weak(storage, old_val, static_cast< storage_type >(new_val), order, memory_order_relaxed));
|
||||
return old_val;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_OPS_EXTENDING_CAS_BASED_HPP_INCLUDED_
|
||||
Reference in New Issue
Block a user