1344cef66SArthur O'Dwyer //===----------------------------------------------------------------------===// 2344cef66SArthur O'Dwyer // 3344cef66SArthur O'Dwyer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4344cef66SArthur O'Dwyer // See https://llvm.org/LICENSE.txt for license information. 5344cef66SArthur O'Dwyer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6344cef66SArthur O'Dwyer // 7344cef66SArthur O'Dwyer //===----------------------------------------------------------------------===// 8344cef66SArthur O'Dwyer 9344cef66SArthur O'Dwyer #ifndef _LIBCPP___RANDOM_PIECEWISE_CONSTANT_DISTRIBUTION_H 10344cef66SArthur O'Dwyer #define _LIBCPP___RANDOM_PIECEWISE_CONSTANT_DISTRIBUTION_H 11344cef66SArthur O'Dwyer 12344cef66SArthur O'Dwyer #include <__algorithm/upper_bound.h> 13344cef66SArthur O'Dwyer #include <__config> 14*e99c4906SNikolas Klauser #include <__cstddef/ptrdiff_t.h> 157624552eSArthur O'Dwyer #include <__random/is_valid.h> 16344cef66SArthur O'Dwyer #include <__random/uniform_real_distribution.h> 172e43a304SNikolas Klauser #include <__vector/vector.h> 182e43a304SNikolas Klauser #include <initializer_list> 19344cef66SArthur O'Dwyer #include <iosfwd> 20344cef66SArthur O'Dwyer #include <numeric> 21344cef66SArthur O'Dwyer 22344cef66SArthur O'Dwyer #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 23344cef66SArthur O'Dwyer # pragma GCC system_header 24344cef66SArthur O'Dwyer #endif 25344cef66SArthur O'Dwyer 26344cef66SArthur O'Dwyer _LIBCPP_PUSH_MACROS 27344cef66SArthur O'Dwyer #include <__undef_macros> 28344cef66SArthur O'Dwyer 29344cef66SArthur O'Dwyer _LIBCPP_BEGIN_NAMESPACE_STD 30344cef66SArthur O'Dwyer 31344cef66SArthur O'Dwyer template <class _RealType = double> 329783f28cSLouis Dionne class _LIBCPP_TEMPLATE_VIS piecewise_constant_distribution { 33727fef79SNhat Nguyen static_assert(__libcpp_random_is_valid_realtype<_RealType>::value, 34727fef79SNhat Nguyen "RealType must be a supported floating-point type"); 35727fef79SNhat Nguyen 36344cef66SArthur O'Dwyer public: 37344cef66SArthur O'Dwyer // types 38344cef66SArthur O'Dwyer typedef _RealType result_type; 39344cef66SArthur O'Dwyer 409783f28cSLouis Dionne class _LIBCPP_TEMPLATE_VIS param_type { 41344cef66SArthur O'Dwyer vector<result_type> __b_; 42344cef66SArthur O'Dwyer vector<result_type> __densities_; 43344cef66SArthur O'Dwyer vector<result_type> __areas_; 449783f28cSLouis Dionne 45344cef66SArthur O'Dwyer public: 46344cef66SArthur O'Dwyer typedef piecewise_constant_distribution distribution_type; 47344cef66SArthur O'Dwyer 4883ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI param_type(); 49344cef66SArthur O'Dwyer template <class _InputIteratorB, class _InputIteratorW> 509783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI param_type(_InputIteratorB __f_b, _InputIteratorB __l_b, _InputIteratorW __f_w); 51344cef66SArthur O'Dwyer #ifndef _LIBCPP_CXX03_LANG 52344cef66SArthur O'Dwyer template <class _UnaryOperation> 5383ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI param_type(initializer_list<result_type> __bl, _UnaryOperation __fw); 54344cef66SArthur O'Dwyer #endif // _LIBCPP_CXX03_LANG 55344cef66SArthur O'Dwyer template <class _UnaryOperation> 569783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI param_type(size_t __nw, result_type __xmin, result_type __xmax, _UnaryOperation __fw); 5783ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI param_type(param_type const&) = default; 5883ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI param_type& operator=(const param_type& __rhs); 59344cef66SArthur O'Dwyer 609783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI vector<result_type> intervals() const { return __b_; } 619783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI vector<result_type> densities() const { return __densities_; } 62344cef66SArthur O'Dwyer 639783f28cSLouis Dionne friend _LIBCPP_HIDE_FROM_ABI bool operator==(const param_type& __x, const param_type& __y) { 649783f28cSLouis Dionne return __x.__densities_ == __y.__densities_ && __x.__b_ == __y.__b_; 659783f28cSLouis Dionne } 669783f28cSLouis Dionne friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const param_type& __x, const param_type& __y) { return !(__x == __y); } 67344cef66SArthur O'Dwyer 68344cef66SArthur O'Dwyer private: 6983ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void __init(); 70344cef66SArthur O'Dwyer 71344cef66SArthur O'Dwyer friend class piecewise_constant_distribution; 72344cef66SArthur O'Dwyer 73344cef66SArthur O'Dwyer template <class _CharT, class _Traits, class _RT> 749783f28cSLouis Dionne friend basic_ostream<_CharT, _Traits>& 759783f28cSLouis Dionne operator<<(basic_ostream<_CharT, _Traits>& __os, const piecewise_constant_distribution<_RT>& __x); 76344cef66SArthur O'Dwyer 77344cef66SArthur O'Dwyer template <class _CharT, class _Traits, class _RT> 789783f28cSLouis Dionne friend basic_istream<_CharT, _Traits>& 799783f28cSLouis Dionne operator>>(basic_istream<_CharT, _Traits>& __is, piecewise_constant_distribution<_RT>& __x); 80344cef66SArthur O'Dwyer }; 81344cef66SArthur O'Dwyer 82344cef66SArthur O'Dwyer private: 83344cef66SArthur O'Dwyer param_type __p_; 84344cef66SArthur O'Dwyer 85344cef66SArthur O'Dwyer public: 86344cef66SArthur O'Dwyer // constructor and reset functions 879783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI piecewise_constant_distribution() {} 88344cef66SArthur O'Dwyer template <class _InputIteratorB, class _InputIteratorW> 894c198542SLouis Dionne _LIBCPP_HIDE_FROM_ABI 909783f28cSLouis Dionne piecewise_constant_distribution(_InputIteratorB __f_b, _InputIteratorB __l_b, _InputIteratorW __f_w) 91b48c5010SNikolas Klauser : __p_(__f_b, __l_b, __f_w) {} 92344cef66SArthur O'Dwyer 93344cef66SArthur O'Dwyer #ifndef _LIBCPP_CXX03_LANG 94344cef66SArthur O'Dwyer template <class _UnaryOperation> 959783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI piecewise_constant_distribution(initializer_list<result_type> __bl, _UnaryOperation __fw) 96344cef66SArthur O'Dwyer : __p_(__bl, __fw) {} 97344cef66SArthur O'Dwyer #endif // _LIBCPP_CXX03_LANG 98344cef66SArthur O'Dwyer 99344cef66SArthur O'Dwyer template <class _UnaryOperation> 1004c198542SLouis Dionne _LIBCPP_HIDE_FROM_ABI 1019783f28cSLouis Dionne piecewise_constant_distribution(size_t __nw, result_type __xmin, result_type __xmax, _UnaryOperation __fw) 102344cef66SArthur O'Dwyer : __p_(__nw, __xmin, __xmax, __fw) {} 103344cef66SArthur O'Dwyer 1049783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI explicit piecewise_constant_distribution(const param_type& __p) : __p_(__p) {} 105344cef66SArthur O'Dwyer 1069783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI void reset() {} 107344cef66SArthur O'Dwyer 108344cef66SArthur O'Dwyer // generating functions 109344cef66SArthur O'Dwyer template <class _URNG> 1109783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g) { 1119783f28cSLouis Dionne return (*this)(__g, __p_); 1129783f28cSLouis Dionne } 11383ce1397SNikolas Klauser template <class _URNG> 11483ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); 115344cef66SArthur O'Dwyer 116344cef66SArthur O'Dwyer // property functions 1179783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI vector<result_type> intervals() const { return __p_.intervals(); } 1189783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI vector<result_type> densities() const { return __p_.densities(); } 119344cef66SArthur O'Dwyer 1209783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI param_type param() const { return __p_; } 1219783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI void param(const param_type& __p) { __p_ = __p; } 122344cef66SArthur O'Dwyer 1239783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI result_type min() const { return __p_.__b_.front(); } 1249783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI result_type max() const { return __p_.__b_.back(); } 125344cef66SArthur O'Dwyer 1269783f28cSLouis Dionne friend _LIBCPP_HIDE_FROM_ABI bool 1279783f28cSLouis Dionne operator==(const piecewise_constant_distribution& __x, const piecewise_constant_distribution& __y) { 1289783f28cSLouis Dionne return __x.__p_ == __y.__p_; 1299783f28cSLouis Dionne } 1309783f28cSLouis Dionne friend _LIBCPP_HIDE_FROM_ABI bool 1319783f28cSLouis Dionne operator!=(const piecewise_constant_distribution& __x, const piecewise_constant_distribution& __y) { 1329783f28cSLouis Dionne return !(__x == __y); 1339783f28cSLouis Dionne } 134344cef66SArthur O'Dwyer 135344cef66SArthur O'Dwyer template <class _CharT, class _Traits, class _RT> 1369783f28cSLouis Dionne friend basic_ostream<_CharT, _Traits>& 1379783f28cSLouis Dionne operator<<(basic_ostream<_CharT, _Traits>& __os, const piecewise_constant_distribution<_RT>& __x); 138344cef66SArthur O'Dwyer 139344cef66SArthur O'Dwyer template <class _CharT, class _Traits, class _RT> 1409783f28cSLouis Dionne friend basic_istream<_CharT, _Traits>& 1419783f28cSLouis Dionne operator>>(basic_istream<_CharT, _Traits>& __is, piecewise_constant_distribution<_RT>& __x); 142344cef66SArthur O'Dwyer }; 143344cef66SArthur O'Dwyer 144344cef66SArthur O'Dwyer template <class _RealType> 145344cef66SArthur O'Dwyer typename piecewise_constant_distribution<_RealType>::param_type& 1469783f28cSLouis Dionne piecewise_constant_distribution<_RealType>::param_type::operator=(const param_type& __rhs) { 147344cef66SArthur O'Dwyer // These can throw 148344cef66SArthur O'Dwyer __b_.reserve(__rhs.__b_.size()); 149344cef66SArthur O'Dwyer __densities_.reserve(__rhs.__densities_.size()); 150344cef66SArthur O'Dwyer __areas_.reserve(__rhs.__areas_.size()); 151344cef66SArthur O'Dwyer 152344cef66SArthur O'Dwyer // These can not throw 153344cef66SArthur O'Dwyer __b_ = __rhs.__b_; 154344cef66SArthur O'Dwyer __densities_ = __rhs.__densities_; 155344cef66SArthur O'Dwyer __areas_ = __rhs.__areas_; 156344cef66SArthur O'Dwyer return *this; 157344cef66SArthur O'Dwyer } 158344cef66SArthur O'Dwyer 159344cef66SArthur O'Dwyer template <class _RealType> 1609783f28cSLouis Dionne void piecewise_constant_distribution<_RealType>::param_type::__init() { 161344cef66SArthur O'Dwyer // __densities_ contains non-normalized areas 1629783f28cSLouis Dionne result_type __total_area = std::accumulate(__densities_.begin(), __densities_.end(), result_type()); 163344cef66SArthur O'Dwyer for (size_t __i = 0; __i < __densities_.size(); ++__i) 164344cef66SArthur O'Dwyer __densities_[__i] /= __total_area; 165344cef66SArthur O'Dwyer // __densities_ contains normalized areas 166344cef66SArthur O'Dwyer __areas_.assign(__densities_.size(), result_type()); 1679783f28cSLouis Dionne std::partial_sum(__densities_.begin(), __densities_.end() - 1, __areas_.begin() + 1); 168344cef66SArthur O'Dwyer // __areas_ contains partial sums of normalized areas: [0, __densities_ - 1] 169344cef66SArthur O'Dwyer __densities_.back() = 1 - __areas_.back(); // correct round off error 170344cef66SArthur O'Dwyer for (size_t __i = 0; __i < __densities_.size(); ++__i) 171344cef66SArthur O'Dwyer __densities_[__i] /= (__b_[__i + 1] - __b_[__i]); 172344cef66SArthur O'Dwyer // __densities_ now contains __densities_ 173344cef66SArthur O'Dwyer } 174344cef66SArthur O'Dwyer 175344cef66SArthur O'Dwyer template <class _RealType> 1769783f28cSLouis Dionne piecewise_constant_distribution<_RealType>::param_type::param_type() : __b_(2), __densities_(1, 1.0), __areas_(1, 0.0) { 177344cef66SArthur O'Dwyer __b_[1] = 1; 178344cef66SArthur O'Dwyer } 179344cef66SArthur O'Dwyer 180344cef66SArthur O'Dwyer template <class _RealType> 181344cef66SArthur O'Dwyer template <class _InputIteratorB, class _InputIteratorW> 182344cef66SArthur O'Dwyer piecewise_constant_distribution<_RealType>::param_type::param_type( 183b48c5010SNikolas Klauser _InputIteratorB __f_b, _InputIteratorB __l_b, _InputIteratorW __f_w) 1849783f28cSLouis Dionne : __b_(__f_b, __l_b) { 1859783f28cSLouis Dionne if (__b_.size() < 2) { 186344cef66SArthur O'Dwyer __b_.resize(2); 187344cef66SArthur O'Dwyer __b_[0] = 0; 188344cef66SArthur O'Dwyer __b_[1] = 1; 189344cef66SArthur O'Dwyer __densities_.assign(1, 1.0); 190344cef66SArthur O'Dwyer __areas_.assign(1, 0.0); 1919783f28cSLouis Dionne } else { 192344cef66SArthur O'Dwyer __densities_.reserve(__b_.size() - 1); 193b48c5010SNikolas Klauser for (size_t __i = 0; __i < __b_.size() - 1; ++__i, ++__f_w) 194b48c5010SNikolas Klauser __densities_.push_back(*__f_w); 195344cef66SArthur O'Dwyer __init(); 196344cef66SArthur O'Dwyer } 197344cef66SArthur O'Dwyer } 198344cef66SArthur O'Dwyer 199344cef66SArthur O'Dwyer #ifndef _LIBCPP_CXX03_LANG 200344cef66SArthur O'Dwyer 201344cef66SArthur O'Dwyer template <class _RealType> 202344cef66SArthur O'Dwyer template <class _UnaryOperation> 203344cef66SArthur O'Dwyer piecewise_constant_distribution<_RealType>::param_type::param_type( 204344cef66SArthur O'Dwyer initializer_list<result_type> __bl, _UnaryOperation __fw) 2059783f28cSLouis Dionne : __b_(__bl.begin(), __bl.end()) { 2069783f28cSLouis Dionne if (__b_.size() < 2) { 207344cef66SArthur O'Dwyer __b_.resize(2); 208344cef66SArthur O'Dwyer __b_[0] = 0; 209344cef66SArthur O'Dwyer __b_[1] = 1; 210344cef66SArthur O'Dwyer __densities_.assign(1, 1.0); 211344cef66SArthur O'Dwyer __areas_.assign(1, 0.0); 2129783f28cSLouis Dionne } else { 213344cef66SArthur O'Dwyer __densities_.reserve(__b_.size() - 1); 214344cef66SArthur O'Dwyer for (size_t __i = 0; __i < __b_.size() - 1; ++__i) 215344cef66SArthur O'Dwyer __densities_.push_back(__fw((__b_[__i + 1] + __b_[__i]) * .5)); 216344cef66SArthur O'Dwyer __init(); 217344cef66SArthur O'Dwyer } 218344cef66SArthur O'Dwyer } 219344cef66SArthur O'Dwyer 220344cef66SArthur O'Dwyer #endif // _LIBCPP_CXX03_LANG 221344cef66SArthur O'Dwyer 222344cef66SArthur O'Dwyer template <class _RealType> 223344cef66SArthur O'Dwyer template <class _UnaryOperation> 224344cef66SArthur O'Dwyer piecewise_constant_distribution<_RealType>::param_type::param_type( 225344cef66SArthur O'Dwyer size_t __nw, result_type __xmin, result_type __xmax, _UnaryOperation __fw) 2269783f28cSLouis Dionne : __b_(__nw == 0 ? 2 : __nw + 1) { 227344cef66SArthur O'Dwyer size_t __n = __b_.size() - 1; 228344cef66SArthur O'Dwyer result_type __d = (__xmax - __xmin) / __n; 229344cef66SArthur O'Dwyer __densities_.reserve(__n); 2309783f28cSLouis Dionne for (size_t __i = 0; __i < __n; ++__i) { 231344cef66SArthur O'Dwyer __b_[__i] = __xmin + __i * __d; 232344cef66SArthur O'Dwyer __densities_.push_back(__fw(__b_[__i] + __d * .5)); 233344cef66SArthur O'Dwyer } 234344cef66SArthur O'Dwyer __b_[__n] = __xmax; 235344cef66SArthur O'Dwyer __init(); 236344cef66SArthur O'Dwyer } 237344cef66SArthur O'Dwyer 238344cef66SArthur O'Dwyer template <class _RealType> 239344cef66SArthur O'Dwyer template <class _URNG> 2409783f28cSLouis Dionne _RealType piecewise_constant_distribution<_RealType>::operator()(_URNG& __g, const param_type& __p) { 2417624552eSArthur O'Dwyer static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); 242344cef66SArthur O'Dwyer typedef uniform_real_distribution<result_type> _Gen; 243344cef66SArthur O'Dwyer result_type __u = _Gen()(__g); 2449783f28cSLouis Dionne ptrdiff_t __k = std::upper_bound(__p.__areas_.begin(), __p.__areas_.end(), __u) - __p.__areas_.begin() - 1; 245344cef66SArthur O'Dwyer return (__u - __p.__areas_[__k]) / __p.__densities_[__k] + __p.__b_[__k]; 246344cef66SArthur O'Dwyer } 247344cef66SArthur O'Dwyer 248344cef66SArthur O'Dwyer template <class _CharT, class _Traits, class _RT> 24980c7e93aSNikolas Klauser _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 2509783f28cSLouis Dionne operator<<(basic_ostream<_CharT, _Traits>& __os, const piecewise_constant_distribution<_RT>& __x) { 251344cef66SArthur O'Dwyer __save_flags<_CharT, _Traits> __lx(__os); 252344cef66SArthur O'Dwyer typedef basic_ostream<_CharT, _Traits> _OStream; 2539783f28cSLouis Dionne __os.flags(_OStream::dec | _OStream::left | _OStream::fixed | _OStream::scientific); 254344cef66SArthur O'Dwyer _CharT __sp = __os.widen(' '); 255344cef66SArthur O'Dwyer __os.fill(__sp); 256344cef66SArthur O'Dwyer size_t __n = __x.__p_.__b_.size(); 257344cef66SArthur O'Dwyer __os << __n; 258344cef66SArthur O'Dwyer for (size_t __i = 0; __i < __n; ++__i) 259344cef66SArthur O'Dwyer __os << __sp << __x.__p_.__b_[__i]; 260344cef66SArthur O'Dwyer __n = __x.__p_.__densities_.size(); 261344cef66SArthur O'Dwyer __os << __sp << __n; 262344cef66SArthur O'Dwyer for (size_t __i = 0; __i < __n; ++__i) 263344cef66SArthur O'Dwyer __os << __sp << __x.__p_.__densities_[__i]; 264344cef66SArthur O'Dwyer __n = __x.__p_.__areas_.size(); 265344cef66SArthur O'Dwyer __os << __sp << __n; 266344cef66SArthur O'Dwyer for (size_t __i = 0; __i < __n; ++__i) 267344cef66SArthur O'Dwyer __os << __sp << __x.__p_.__areas_[__i]; 268344cef66SArthur O'Dwyer return __os; 269344cef66SArthur O'Dwyer } 270344cef66SArthur O'Dwyer 271344cef66SArthur O'Dwyer template <class _CharT, class _Traits, class _RT> 27280c7e93aSNikolas Klauser _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& 2739783f28cSLouis Dionne operator>>(basic_istream<_CharT, _Traits>& __is, piecewise_constant_distribution<_RT>& __x) { 274344cef66SArthur O'Dwyer typedef piecewise_constant_distribution<_RT> _Eng; 275344cef66SArthur O'Dwyer typedef typename _Eng::result_type result_type; 276344cef66SArthur O'Dwyer __save_flags<_CharT, _Traits> __lx(__is); 277344cef66SArthur O'Dwyer typedef basic_istream<_CharT, _Traits> _Istream; 278344cef66SArthur O'Dwyer __is.flags(_Istream::dec | _Istream::skipws); 279344cef66SArthur O'Dwyer size_t __n; 280344cef66SArthur O'Dwyer __is >> __n; 281344cef66SArthur O'Dwyer vector<result_type> __b(__n); 282344cef66SArthur O'Dwyer for (size_t __i = 0; __i < __n; ++__i) 283344cef66SArthur O'Dwyer __is >> __b[__i]; 284344cef66SArthur O'Dwyer __is >> __n; 285344cef66SArthur O'Dwyer vector<result_type> __densities(__n); 286344cef66SArthur O'Dwyer for (size_t __i = 0; __i < __n; ++__i) 287344cef66SArthur O'Dwyer __is >> __densities[__i]; 288344cef66SArthur O'Dwyer __is >> __n; 289344cef66SArthur O'Dwyer vector<result_type> __areas(__n); 290344cef66SArthur O'Dwyer for (size_t __i = 0; __i < __n; ++__i) 291344cef66SArthur O'Dwyer __is >> __areas[__i]; 2929783f28cSLouis Dionne if (!__is.fail()) { 293344cef66SArthur O'Dwyer swap(__x.__p_.__b_, __b); 294344cef66SArthur O'Dwyer swap(__x.__p_.__densities_, __densities); 295344cef66SArthur O'Dwyer swap(__x.__p_.__areas_, __areas); 296344cef66SArthur O'Dwyer } 297344cef66SArthur O'Dwyer return __is; 298344cef66SArthur O'Dwyer } 299344cef66SArthur O'Dwyer 300344cef66SArthur O'Dwyer _LIBCPP_END_NAMESPACE_STD 301344cef66SArthur O'Dwyer 302344cef66SArthur O'Dwyer _LIBCPP_POP_MACROS 303344cef66SArthur O'Dwyer 304344cef66SArthur O'Dwyer #endif // _LIBCPP___RANDOM_PIECEWISE_CONSTANT_DISTRIBUTION_H 305