1 // Copyright 2019 The Abseil Authors.
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
7 // https://www.apache.org/licenses/LICENSE-2.0
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.
15 #ifndef ABSL_RANDOM_UNIFORM_HELPER_H_
16 #define ABSL_RANDOM_UNIFORM_HELPER_H_
20 #include <type_traits>
22 #include "absl/meta/type_traits.h"
25 template <typename IntType>
26 class uniform_int_distribution;
28 template <typename RealType>
29 class uniform_real_distribution;
31 // Interval tag types which specify whether the interval is open or closed
32 // on either boundary.
33 namespace random_internal {
34 struct IntervalClosedClosedT {};
35 struct IntervalClosedOpenT {};
36 struct IntervalOpenClosedT {};
37 struct IntervalOpenOpenT {};
38 } // namespace random_internal
40 namespace random_internal {
43 // uniform_lower_bound(tag, a, b)
45 // uniform_upper_bound(tag, a, b)
46 // are used as implementation-details for absl::Uniform().
49 // [a, b] == [uniform_lower_bound(IntervalClosedClosed, a, b),
50 // uniform_upper_bound(IntervalClosedClosed, a, b)]
51 // (a, b) == [uniform_lower_bound(IntervalOpenOpen, a, b),
52 // uniform_upper_bound(IntervalOpenOpen, a, b)]
53 // [a, b) == [uniform_lower_bound(IntervalClosedOpen, a, b),
54 // uniform_upper_bound(IntervalClosedOpen, a, b)]
55 // (a, b] == [uniform_lower_bound(IntervalOpenClosed, a, b),
56 // uniform_upper_bound(IntervalOpenClosed, a, b)]
58 template <typename IntType, typename Tag>
59 typename absl::enable_if_t<
61 std::is_integral<IntType>,
62 absl::disjunction<std::is_same<Tag, IntervalOpenClosedT>,
63 std::is_same<Tag, IntervalOpenOpenT>>>::value,
65 uniform_lower_bound(Tag, IntType a, IntType) {
69 template <typename FloatType, typename Tag>
70 typename absl::enable_if_t<
72 std::is_floating_point<FloatType>,
73 absl::disjunction<std::is_same<Tag, IntervalOpenClosedT>,
74 std::is_same<Tag, IntervalOpenOpenT>>>::value,
76 uniform_lower_bound(Tag, FloatType a, FloatType b) {
77 return std::nextafter(a, b);
80 template <typename NumType, typename Tag>
81 typename absl::enable_if_t<
82 absl::disjunction<std::is_same<Tag, IntervalClosedClosedT>,
83 std::is_same<Tag, IntervalClosedOpenT>>::value,
85 uniform_lower_bound(Tag, NumType a, NumType) {
89 template <typename IntType, typename Tag>
90 typename absl::enable_if_t<
92 std::is_integral<IntType>,
93 absl::disjunction<std::is_same<Tag, IntervalClosedOpenT>,
94 std::is_same<Tag, IntervalOpenOpenT>>>::value,
96 uniform_upper_bound(Tag, IntType, IntType b) {
100 template <typename FloatType, typename Tag>
101 typename absl::enable_if_t<
103 std::is_floating_point<FloatType>,
104 absl::disjunction<std::is_same<Tag, IntervalClosedOpenT>,
105 std::is_same<Tag, IntervalOpenOpenT>>>::value,
107 uniform_upper_bound(Tag, FloatType, FloatType b) {
111 template <typename IntType, typename Tag>
112 typename absl::enable_if_t<
114 std::is_integral<IntType>,
115 absl::disjunction<std::is_same<Tag, IntervalClosedClosedT>,
116 std::is_same<Tag, IntervalOpenClosedT>>>::value,
118 uniform_upper_bound(Tag, IntType, IntType b) {
122 template <typename FloatType, typename Tag>
123 typename absl::enable_if_t<
125 std::is_floating_point<FloatType>,
126 absl::disjunction<std::is_same<Tag, IntervalClosedClosedT>,
127 std::is_same<Tag, IntervalOpenClosedT>>>::value,
129 uniform_upper_bound(Tag, FloatType, FloatType b) {
130 return std::nextafter(b, (std::numeric_limits<FloatType>::max)());
133 template <typename NumType>
134 using UniformDistribution =
135 typename std::conditional<std::is_integral<NumType>::value,
136 absl::uniform_int_distribution<NumType>,
137 absl::uniform_real_distribution<NumType>>::type;
139 template <typename TagType, typename NumType>
140 struct UniformDistributionWrapper : public UniformDistribution<NumType> {
141 explicit UniformDistributionWrapper(NumType lo, NumType hi)
142 : UniformDistribution<NumType>(
143 uniform_lower_bound<NumType>(TagType{}, lo, hi),
144 uniform_upper_bound<NumType>(TagType{}, lo, hi)) {}
147 } // namespace random_internal
150 #endif // ABSL_RANDOM_UNIFORM_HELPER_H_