blob: 963b7690f1a9fb3551933935723aff1c682a1803 [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001// Copyright 2017 The Abseil Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef ABSL_RANDOM_INTERNAL_FASTMATH_H_
16#define ABSL_RANDOM_INTERNAL_FASTMATH_H_
17
18// This file contains fast math functions (bitwise ops as well as some others)
19// which are implementation details of various absl random number distributions.
20
21#include <cassert>
22#include <cmath>
23#include <cstdint>
24
Austin Schuhb4691e92020-12-31 12:37:18 -080025#include "absl/numeric/bits.h"
Austin Schuh36244a12019-09-21 17:52:38 -070026
27namespace absl {
Austin Schuhb4691e92020-12-31 12:37:18 -080028ABSL_NAMESPACE_BEGIN
Austin Schuh36244a12019-09-21 17:52:38 -070029namespace random_internal {
30
Austin Schuh36244a12019-09-21 17:52:38 -070031// Compute log2(n) using integer operations.
32// While std::log2 is more accurate than std::log(n) / std::log(2), for
33// very large numbers--those close to std::numeric_limits<uint64_t>::max() - 2,
34// for instance--std::log2 rounds up rather than down, which introduces
35// definite skew in the results.
36inline int IntLog2Floor(uint64_t n) {
Austin Schuhb4691e92020-12-31 12:37:18 -080037 return (n <= 1) ? 0 : (63 - countl_zero(n));
Austin Schuh36244a12019-09-21 17:52:38 -070038}
39inline int IntLog2Ceil(uint64_t n) {
Austin Schuhb4691e92020-12-31 12:37:18 -080040 return (n <= 1) ? 0 : (64 - countl_zero(n - 1));
Austin Schuh36244a12019-09-21 17:52:38 -070041}
42
43inline double StirlingLogFactorial(double n) {
44 assert(n >= 1);
45 // Using Stirling's approximation.
46 constexpr double kLog2PI = 1.83787706640934548356;
47 const double logn = std::log(n);
48 const double ninv = 1.0 / static_cast<double>(n);
49 return n * logn - n + 0.5 * (kLog2PI + logn) + (1.0 / 12.0) * ninv -
50 (1.0 / 360.0) * ninv * ninv * ninv;
51}
52
Austin Schuh36244a12019-09-21 17:52:38 -070053} // namespace random_internal
Austin Schuhb4691e92020-12-31 12:37:18 -080054ABSL_NAMESPACE_END
Austin Schuh36244a12019-09-21 17:52:38 -070055} // namespace absl
56
57#endif // ABSL_RANDOM_INTERNAL_FASTMATH_H_