bernoulli_details.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright 2013 John Maddock
  3. // Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_MATH_BERNOULLI_DETAIL_HPP
  7. #define BOOST_MATH_BERNOULLI_DETAIL_HPP
  8. #include <boost/config.hpp>
  9. #include <boost/detail/lightweight_mutex.hpp>
  10. #include <boost/math/tools/atomic.hpp>
  11. #include <boost/utility/enable_if.hpp>
  12. #include <boost/math/tools/toms748_solve.hpp>
  13. #include <boost/math/tools/cxx03_warn.hpp>
  14. #include <vector>
  15. namespace boost{ namespace math{ namespace detail{
  16. //
  17. // Asymptotic expansion for B2n due to
  18. // Luschny LogB3 formula (http://www.luschny.de/math/primes/bernincl.html)
  19. //
  20. template <class T, class Policy>
  21. T b2n_asymptotic(int n)
  22. {
  23. BOOST_MATH_STD_USING
  24. const T nx = static_cast<T>(n);
  25. const T nx2(nx * nx);
  26. const T approximate_log_of_bernoulli_bn =
  27. ((boost::math::constants::half<T>() + nx) * log(nx))
  28. + ((boost::math::constants::half<T>() - nx) * log(boost::math::constants::pi<T>()))
  29. + (((T(3) / 2) - nx) * boost::math::constants::ln_two<T>())
  30. + ((nx * (T(2) - (nx2 * 7) * (1 + ((nx2 * 30) * ((nx2 * 12) - 1))))) / (((nx2 * nx2) * nx2) * 2520));
  31. return ((n / 2) & 1 ? 1 : -1) * (approximate_log_of_bernoulli_bn > tools::log_max_value<T>()
  32. ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, nx, Policy())
  33. : static_cast<T>(exp(approximate_log_of_bernoulli_bn)));
  34. }
  35. template <class T, class Policy>
  36. T t2n_asymptotic(int n)
  37. {
  38. BOOST_MATH_STD_USING
  39. // Just get B2n and convert to a Tangent number:
  40. T t2n = fabs(b2n_asymptotic<T, Policy>(2 * n)) / (2 * n);
  41. T p2 = ldexp(T(1), n);
  42. if(tools::max_value<T>() / p2 < t2n)
  43. return policies::raise_overflow_error<T>("boost::math::tangent_t2n<%1%>(std::size_t)", 0, T(n), Policy());
  44. t2n *= p2;
  45. p2 -= 1;
  46. if(tools::max_value<T>() / p2 < t2n)
  47. return policies::raise_overflow_error<T>("boost::math::tangent_t2n<%1%>(std::size_t)", 0, Policy());
  48. t2n *= p2;
  49. return t2n;
  50. }
  51. //
  52. // We need to know the approximate value of /n/ which will
  53. // cause bernoulli_b2n<T>(n) to return infinity - this allows
  54. // us to elude a great deal of runtime checking for values below
  55. // n, and only perform the full overflow checks when we know that we're
  56. // getting close to the point where our calculations will overflow.
  57. // We use Luschny's LogB3 formula (http://www.luschny.de/math/primes/bernincl.html)
  58. // to find the limit, and since we're dealing with the log of the Bernoulli numbers
  59. // we need only perform the calculation at double precision and not with T
  60. // (which may be a multiprecision type). The limit returned is within 1 of the true
  61. // limit for all the types tested. Note that although the code below is basically
  62. // the same as b2n_asymptotic above, it has been recast as a continuous real-valued
  63. // function as this makes the root finding go smoother/faster. It also omits the
  64. // sign of the Bernoulli number.
  65. //
  66. struct max_bernoulli_root_functor
  67. {
  68. max_bernoulli_root_functor(ulong_long_type t) : target(static_cast<double>(t)) {}
  69. double operator()(double n)
  70. {
  71. BOOST_MATH_STD_USING
  72. // Luschny LogB3(n) formula.
  73. const double nx2(n * n);
  74. const double approximate_log_of_bernoulli_bn
  75. = ((boost::math::constants::half<double>() + n) * log(n))
  76. + ((boost::math::constants::half<double>() - n) * log(boost::math::constants::pi<double>()))
  77. + (((double(3) / 2) - n) * boost::math::constants::ln_two<double>())
  78. + ((n * (2 - (nx2 * 7) * (1 + ((nx2 * 30) * ((nx2 * 12) - 1))))) / (((nx2 * nx2) * nx2) * 2520));
  79. return approximate_log_of_bernoulli_bn - target;
  80. }
  81. private:
  82. double target;
  83. };
  84. template <class T, class Policy>
  85. inline std::size_t find_bernoulli_overflow_limit(const boost::false_type&)
  86. {
  87. // Set a limit on how large the result can ever be:
  88. static const double max_result = static_cast<double>((std::numeric_limits<std::size_t>::max)() - 1000u);
  89. ulong_long_type t = lltrunc(boost::math::tools::log_max_value<T>());
  90. max_bernoulli_root_functor fun(t);
  91. boost::math::tools::equal_floor tol;
  92. boost::uintmax_t max_iter = boost::math::policies::get_max_root_iterations<Policy>();
  93. double result = boost::math::tools::toms748_solve(fun, sqrt(double(t)), double(t), tol, max_iter).first / 2;
  94. if (result > max_result)
  95. result = max_result;
  96. return static_cast<std::size_t>(result);
  97. }
  98. template <class T, class Policy>
  99. inline std::size_t find_bernoulli_overflow_limit(const boost::true_type&)
  100. {
  101. return max_bernoulli_index<bernoulli_imp_variant<T>::value>::value;
  102. }
  103. template <class T, class Policy>
  104. std::size_t b2n_overflow_limit()
  105. {
  106. // This routine is called at program startup if it's called at all:
  107. // that guarantees safe initialization of the static variable.
  108. typedef boost::integral_constant<bool, (bernoulli_imp_variant<T>::value >= 1) && (bernoulli_imp_variant<T>::value <= 3)> tag_type;
  109. static const std::size_t lim = find_bernoulli_overflow_limit<T, Policy>(tag_type());
  110. return lim;
  111. }
  112. //
  113. // The tangent numbers grow larger much more rapidly than the Bernoulli numbers do....
  114. // so to compute the Bernoulli numbers from the tangent numbers, we need to avoid spurious
  115. // overflow in the calculation, we can do this by scaling all the tangent number by some scale factor:
  116. //
  117. template <class T>
  118. inline typename enable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2), T>::type tangent_scale_factor()
  119. {
  120. BOOST_MATH_STD_USING
  121. return ldexp(T(1), std::numeric_limits<T>::min_exponent + 5);
  122. }
  123. template <class T>
  124. inline typename disable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2), T>::type tangent_scale_factor()
  125. {
  126. return tools::min_value<T>() * 16;
  127. }
  128. //
  129. // Initializer: ensure all our constants are initialized prior to the first call of main:
  130. //
  131. template <class T, class Policy>
  132. struct bernoulli_initializer
  133. {
  134. struct init
  135. {
  136. init()
  137. {
  138. //
  139. // We call twice, once to initialize our static table, and once to
  140. // initialize our dymanic table:
  141. //
  142. boost::math::bernoulli_b2n<T>(2, Policy());
  143. #ifndef BOOST_NO_EXCEPTIONS
  144. try{
  145. #endif
  146. boost::math::bernoulli_b2n<T>(max_bernoulli_b2n<T>::value + 1, Policy());
  147. #ifndef BOOST_NO_EXCEPTIONS
  148. } catch(const std::overflow_error&){}
  149. #endif
  150. boost::math::tangent_t2n<T>(2, Policy());
  151. }
  152. void force_instantiate()const{}
  153. };
  154. static const init initializer;
  155. static void force_instantiate()
  156. {
  157. initializer.force_instantiate();
  158. }
  159. };
  160. template <class T, class Policy>
  161. const typename bernoulli_initializer<T, Policy>::init bernoulli_initializer<T, Policy>::initializer;
  162. //
  163. // We need something to act as a cache for our calculated Bernoulli numbers. In order to
  164. // ensure both fast access and thread safety, we need a stable table which may be extended
  165. // in size, but which never reallocates: that way values already calculated may be accessed
  166. // concurrently with another thread extending the table with new values.
  167. //
  168. // Very very simple vector class that will never allocate more than once, we could use
  169. // boost::container::static_vector here, but that allocates on the stack, which may well
  170. // cause issues for the amount of memory we want in the extreme case...
  171. //
  172. template <class T>
  173. struct fixed_vector : private std::allocator<T>
  174. {
  175. typedef unsigned size_type;
  176. typedef T* iterator;
  177. typedef const T* const_iterator;
  178. fixed_vector() : m_used(0)
  179. {
  180. std::size_t overflow_limit = 5 + b2n_overflow_limit<T, policies::policy<> >();
  181. m_capacity = static_cast<unsigned>((std::min)(overflow_limit, static_cast<std::size_t>(100000u)));
  182. m_data = this->allocate(m_capacity);
  183. }
  184. ~fixed_vector()
  185. {
  186. #ifdef BOOST_NO_CXX11_ALLOCATOR
  187. for(unsigned i = 0; i < m_used; ++i)
  188. this->destroy(&m_data[i]);
  189. this->deallocate(m_data, m_capacity);
  190. #else
  191. typedef std::allocator<T> allocator_type;
  192. typedef std::allocator_traits<allocator_type> allocator_traits;
  193. allocator_type& alloc = *this;
  194. for(unsigned i = 0; i < m_used; ++i)
  195. allocator_traits::destroy(alloc, &m_data[i]);
  196. allocator_traits::deallocate(alloc, m_data, m_capacity);
  197. #endif
  198. }
  199. T& operator[](unsigned n) { BOOST_ASSERT(n < m_used); return m_data[n]; }
  200. const T& operator[](unsigned n)const { BOOST_ASSERT(n < m_used); return m_data[n]; }
  201. unsigned size()const { return m_used; }
  202. unsigned size() { return m_used; }
  203. void resize(unsigned n, const T& val)
  204. {
  205. if(n > m_capacity)
  206. {
  207. BOOST_THROW_EXCEPTION(std::runtime_error("Exhausted storage for Bernoulli numbers."));
  208. }
  209. for(unsigned i = m_used; i < n; ++i)
  210. new (m_data + i) T(val);
  211. m_used = n;
  212. }
  213. void resize(unsigned n) { resize(n, T()); }
  214. T* begin() { return m_data; }
  215. T* end() { return m_data + m_used; }
  216. T* begin()const { return m_data; }
  217. T* end()const { return m_data + m_used; }
  218. unsigned capacity()const { return m_capacity; }
  219. void clear() { m_used = 0; }
  220. private:
  221. T* m_data;
  222. unsigned m_used, m_capacity;
  223. };
  224. template <class T, class Policy>
  225. class bernoulli_numbers_cache
  226. {
  227. public:
  228. bernoulli_numbers_cache() : m_overflow_limit((std::numeric_limits<std::size_t>::max)())
  229. #if defined(BOOST_HAS_THREADS) && !defined(BOOST_MATH_NO_ATOMIC_INT)
  230. , m_counter(0)
  231. #endif
  232. , m_current_precision(boost::math::tools::digits<T>())
  233. {}
  234. typedef fixed_vector<T> container_type;
  235. void tangent(std::size_t m)
  236. {
  237. static const std::size_t min_overflow_index = b2n_overflow_limit<T, Policy>() - 1;
  238. tn.resize(static_cast<typename container_type::size_type>(m), T(0U));
  239. BOOST_MATH_INSTRUMENT_VARIABLE(min_overflow_index);
  240. std::size_t prev_size = m_intermediates.size();
  241. m_intermediates.resize(m, T(0U));
  242. if(prev_size == 0)
  243. {
  244. m_intermediates[1] = tangent_scale_factor<T>() /*T(1U)*/;
  245. tn[0U] = T(0U);
  246. tn[1U] = tangent_scale_factor<T>()/* T(1U)*/;
  247. BOOST_MATH_INSTRUMENT_VARIABLE(tn[0]);
  248. BOOST_MATH_INSTRUMENT_VARIABLE(tn[1]);
  249. }
  250. for(std::size_t i = std::max<size_t>(2, prev_size); i < m; i++)
  251. {
  252. bool overflow_check = false;
  253. if(i >= min_overflow_index && (boost::math::tools::max_value<T>() / (i-1) < m_intermediates[1]) )
  254. {
  255. std::fill(tn.begin() + i, tn.end(), boost::math::tools::max_value<T>());
  256. break;
  257. }
  258. m_intermediates[1] = m_intermediates[1] * (i-1);
  259. for(std::size_t j = 2; j <= i; j++)
  260. {
  261. overflow_check =
  262. (i >= min_overflow_index) && (
  263. (boost::math::tools::max_value<T>() / (i - j) < m_intermediates[j])
  264. || (boost::math::tools::max_value<T>() / (i - j + 2) < m_intermediates[j-1])
  265. || (boost::math::tools::max_value<T>() - m_intermediates[j] * (i - j) < m_intermediates[j-1] * (i - j + 2))
  266. || ((boost::math::isinf)(m_intermediates[j]))
  267. );
  268. if(overflow_check)
  269. {
  270. std::fill(tn.begin() + i, tn.end(), boost::math::tools::max_value<T>());
  271. break;
  272. }
  273. m_intermediates[j] = m_intermediates[j] * (i - j) + m_intermediates[j-1] * (i - j + 2);
  274. }
  275. if(overflow_check)
  276. break; // already filled the tn...
  277. tn[static_cast<typename container_type::size_type>(i)] = m_intermediates[i];
  278. BOOST_MATH_INSTRUMENT_VARIABLE(i);
  279. BOOST_MATH_INSTRUMENT_VARIABLE(tn[static_cast<typename container_type::size_type>(i)]);
  280. }
  281. }
  282. void tangent_numbers_series(const std::size_t m)
  283. {
  284. BOOST_MATH_STD_USING
  285. static const std::size_t min_overflow_index = b2n_overflow_limit<T, Policy>() - 1;
  286. typename container_type::size_type old_size = bn.size();
  287. tangent(m);
  288. bn.resize(static_cast<typename container_type::size_type>(m));
  289. if(!old_size)
  290. {
  291. bn[0] = 1;
  292. old_size = 1;
  293. }
  294. T power_two(ldexp(T(1), static_cast<int>(2 * old_size)));
  295. for(std::size_t i = old_size; i < m; i++)
  296. {
  297. T b(static_cast<T>(i * 2));
  298. //
  299. // Not only do we need to take care to avoid spurious over/under flow in
  300. // the calculation, but we also need to avoid overflow altogether in case
  301. // we're calculating with a type where "bad things" happen in that case:
  302. //
  303. b = b / (power_two * tangent_scale_factor<T>());
  304. b /= (power_two - 1);
  305. bool overflow_check = (i >= min_overflow_index) && (tools::max_value<T>() / tn[static_cast<typename container_type::size_type>(i)] < b);
  306. if(overflow_check)
  307. {
  308. m_overflow_limit = i;
  309. while(i < m)
  310. {
  311. b = std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : tools::max_value<T>();
  312. bn[static_cast<typename container_type::size_type>(i)] = ((i % 2U) ? b : T(-b));
  313. ++i;
  314. }
  315. break;
  316. }
  317. else
  318. {
  319. b *= tn[static_cast<typename container_type::size_type>(i)];
  320. }
  321. power_two = ldexp(power_two, 2);
  322. const bool b_neg = i % 2 == 0;
  323. bn[static_cast<typename container_type::size_type>(i)] = ((!b_neg) ? b : T(-b));
  324. }
  325. }
  326. template <class OutputIterator>
  327. OutputIterator copy_bernoulli_numbers(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol)
  328. {
  329. //
  330. // There are basically 3 thread safety options:
  331. //
  332. // 1) There are no threads (BOOST_HAS_THREADS is not defined).
  333. // 2) There are threads, but we do not have a true atomic integer type,
  334. // in this case we just use a mutex to guard against race conditions.
  335. // 3) There are threads, and we have an atomic integer: in this case we can
  336. // use the double-checked locking pattern to avoid thread synchronisation
  337. // when accessing values already in the cache.
  338. //
  339. // First off handle the common case for overflow and/or asymptotic expansion:
  340. //
  341. if(start + n > bn.capacity())
  342. {
  343. if(start < bn.capacity())
  344. {
  345. out = copy_bernoulli_numbers(out, start, bn.capacity() - start, pol);
  346. n -= bn.capacity() - start;
  347. start = static_cast<std::size_t>(bn.capacity());
  348. }
  349. if(start < b2n_overflow_limit<T, Policy>() + 2u)
  350. {
  351. for(; n; ++start, --n)
  352. {
  353. *out = b2n_asymptotic<T, Policy>(static_cast<typename container_type::size_type>(start * 2U));
  354. ++out;
  355. }
  356. }
  357. for(; n; ++start, --n)
  358. {
  359. *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(start), pol);
  360. ++out;
  361. }
  362. return out;
  363. }
  364. #if !defined(BOOST_HAS_THREADS)
  365. //
  366. // Single threaded code, very simple:
  367. //
  368. if(m_current_precision < boost::math::tools::digits<T>())
  369. {
  370. bn.clear();
  371. tn.clear();
  372. m_intermediates.clear();
  373. m_current_precision = boost::math::tools::digits<T>();
  374. }
  375. if(start + n >= bn.size())
  376. {
  377. std::size_t new_size = (std::min)((std::max)((std::max)(std::size_t(start + n), std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
  378. tangent_numbers_series(new_size);
  379. }
  380. for(std::size_t i = (std::max)(std::size_t(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
  381. {
  382. *out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[i];
  383. ++out;
  384. }
  385. #elif defined(BOOST_MATH_NO_ATOMIC_INT)
  386. //
  387. // We need to grab a mutex every time we get here, for both readers and writers:
  388. //
  389. boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
  390. if(m_current_precision < boost::math::tools::digits<T>())
  391. {
  392. bn.clear();
  393. tn.clear();
  394. m_intermediates.clear();
  395. m_current_precision = boost::math::tools::digits<T>();
  396. }
  397. if(start + n >= bn.size())
  398. {
  399. std::size_t new_size = (std::min)((std::max)((std::max)(std::size_t(start + n), std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
  400. tangent_numbers_series(new_size);
  401. }
  402. for(std::size_t i = (std::max)(std::size_t(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
  403. {
  404. *out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[i];
  405. ++out;
  406. }
  407. #else
  408. //
  409. // Double-checked locking pattern, lets us access cached already cached values
  410. // without locking:
  411. //
  412. // Get the counter and see if we need to calculate more constants:
  413. //
  414. if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
  415. || (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()))
  416. {
  417. boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
  418. if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
  419. || (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()))
  420. {
  421. if(static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>())
  422. {
  423. bn.clear();
  424. tn.clear();
  425. m_intermediates.clear();
  426. m_counter.store(0, BOOST_MATH_ATOMIC_NS::memory_order_release);
  427. m_current_precision = boost::math::tools::digits<T>();
  428. }
  429. if(start + n >= bn.size())
  430. {
  431. std::size_t new_size = (std::min)((std::max)((std::max)(std::size_t(start + n), std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
  432. tangent_numbers_series(new_size);
  433. }
  434. m_counter.store(static_cast<atomic_integer_type>(bn.size()), BOOST_MATH_ATOMIC_NS::memory_order_release);
  435. }
  436. }
  437. for(std::size_t i = (std::max)(static_cast<std::size_t>(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
  438. {
  439. *out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[static_cast<typename container_type::size_type>(i)];
  440. ++out;
  441. }
  442. #endif
  443. return out;
  444. }
  445. template <class OutputIterator>
  446. OutputIterator copy_tangent_numbers(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol)
  447. {
  448. //
  449. // There are basically 3 thread safety options:
  450. //
  451. // 1) There are no threads (BOOST_HAS_THREADS is not defined).
  452. // 2) There are threads, but we do not have a true atomic integer type,
  453. // in this case we just use a mutex to guard against race conditions.
  454. // 3) There are threads, and we have an atomic integer: in this case we can
  455. // use the double-checked locking pattern to avoid thread synchronisation
  456. // when accessing values already in the cache.
  457. //
  458. //
  459. // First off handle the common case for overflow and/or asymptotic expansion:
  460. //
  461. if(start + n > bn.capacity())
  462. {
  463. if(start < bn.capacity())
  464. {
  465. out = copy_tangent_numbers(out, start, bn.capacity() - start, pol);
  466. n -= bn.capacity() - start;
  467. start = static_cast<std::size_t>(bn.capacity());
  468. }
  469. if(start < b2n_overflow_limit<T, Policy>() + 2u)
  470. {
  471. for(; n; ++start, --n)
  472. {
  473. *out = t2n_asymptotic<T, Policy>(static_cast<typename container_type::size_type>(start));
  474. ++out;
  475. }
  476. }
  477. for(; n; ++start, --n)
  478. {
  479. *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(start), pol);
  480. ++out;
  481. }
  482. return out;
  483. }
  484. #if !defined(BOOST_HAS_THREADS)
  485. //
  486. // Single threaded code, very simple:
  487. //
  488. if(m_current_precision < boost::math::tools::digits<T>())
  489. {
  490. bn.clear();
  491. tn.clear();
  492. m_intermediates.clear();
  493. m_current_precision = boost::math::tools::digits<T>();
  494. }
  495. if(start + n >= bn.size())
  496. {
  497. std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
  498. tangent_numbers_series(new_size);
  499. }
  500. for(std::size_t i = start; i < start + n; ++i)
  501. {
  502. if(i >= m_overflow_limit)
  503. *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
  504. else
  505. {
  506. if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)])
  507. *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
  508. else
  509. *out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>();
  510. }
  511. ++out;
  512. }
  513. #elif defined(BOOST_MATH_NO_ATOMIC_INT)
  514. //
  515. // We need to grab a mutex every time we get here, for both readers and writers:
  516. //
  517. boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
  518. if(m_current_precision < boost::math::tools::digits<T>())
  519. {
  520. bn.clear();
  521. tn.clear();
  522. m_intermediates.clear();
  523. m_current_precision = boost::math::tools::digits<T>();
  524. }
  525. if(start + n >= bn.size())
  526. {
  527. std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
  528. tangent_numbers_series(new_size);
  529. }
  530. for(std::size_t i = start; i < start + n; ++i)
  531. {
  532. if(i >= m_overflow_limit)
  533. *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
  534. else
  535. {
  536. if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)])
  537. *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
  538. else
  539. *out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>();
  540. }
  541. ++out;
  542. }
  543. #else
  544. //
  545. // Double-checked locking pattern, lets us access cached already cached values
  546. // without locking:
  547. //
  548. // Get the counter and see if we need to calculate more constants:
  549. //
  550. if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
  551. || (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()))
  552. {
  553. boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
  554. if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
  555. || (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()))
  556. {
  557. if(static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>())
  558. {
  559. bn.clear();
  560. tn.clear();
  561. m_intermediates.clear();
  562. m_counter.store(0, BOOST_MATH_ATOMIC_NS::memory_order_release);
  563. m_current_precision = boost::math::tools::digits<T>();
  564. }
  565. if(start + n >= bn.size())
  566. {
  567. std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
  568. tangent_numbers_series(new_size);
  569. }
  570. m_counter.store(static_cast<atomic_integer_type>(bn.size()), BOOST_MATH_ATOMIC_NS::memory_order_release);
  571. }
  572. }
  573. for(std::size_t i = start; i < start + n; ++i)
  574. {
  575. if(i >= m_overflow_limit)
  576. *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
  577. else
  578. {
  579. if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)])
  580. *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
  581. else
  582. *out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>();
  583. }
  584. ++out;
  585. }
  586. #endif
  587. return out;
  588. }
  589. private:
  590. //
  591. // The caches for Bernoulli and tangent numbers, once allocated,
  592. // these must NEVER EVER reallocate as it breaks our thread
  593. // safety guarantees:
  594. //
  595. fixed_vector<T> bn, tn;
  596. std::vector<T> m_intermediates;
  597. // The value at which we know overflow has already occurred for the Bn:
  598. std::size_t m_overflow_limit;
  599. #if !defined(BOOST_HAS_THREADS)
  600. int m_current_precision;
  601. #elif defined(BOOST_MATH_NO_ATOMIC_INT)
  602. boost::detail::lightweight_mutex m_mutex;
  603. int m_current_precision;
  604. #else
  605. boost::detail::lightweight_mutex m_mutex;
  606. atomic_counter_type m_counter, m_current_precision;
  607. #endif
  608. };
  609. template <class T, class Policy>
  610. inline bernoulli_numbers_cache<T, Policy>& get_bernoulli_numbers_cache()
  611. {
  612. //
  613. // Force this function to be called at program startup so all the static variables
  614. // get initialized then (thread safety).
  615. //
  616. bernoulli_initializer<T, Policy>::force_instantiate();
  617. static bernoulli_numbers_cache<T, Policy> data;
  618. return data;
  619. }
  620. }}}
  621. #endif // BOOST_MATH_BERNOULLI_DETAIL_HPP