Path: blob/main/contrib/llvm-project/libcxx/include/__random/piecewise_linear_distribution.h
35233 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef _LIBCPP___RANDOM_PIECEWISE_LINEAR_DISTRIBUTION_H9#define _LIBCPP___RANDOM_PIECEWISE_LINEAR_DISTRIBUTION_H1011#include <__algorithm/upper_bound.h>12#include <__config>13#include <__random/is_valid.h>14#include <__random/uniform_real_distribution.h>15#include <cmath>16#include <iosfwd>17#include <vector>1819#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)20# pragma GCC system_header21#endif2223_LIBCPP_PUSH_MACROS24#include <__undef_macros>2526_LIBCPP_BEGIN_NAMESPACE_STD2728template <class _RealType = double>29class _LIBCPP_TEMPLATE_VIS piecewise_linear_distribution {30static_assert(__libcpp_random_is_valid_realtype<_RealType>::value,31"RealType must be a supported floating-point type");3233public:34// types35typedef _RealType result_type;3637class _LIBCPP_TEMPLATE_VIS param_type {38vector<result_type> __b_;39vector<result_type> __densities_;40vector<result_type> __areas_;4142public:43typedef piecewise_linear_distribution distribution_type;4445_LIBCPP_HIDE_FROM_ABI param_type();46template <class _InputIteratorB, class _InputIteratorW>47_LIBCPP_HIDE_FROM_ABI param_type(_InputIteratorB __f_b, _InputIteratorB __l_b, _InputIteratorW __f_w);48#ifndef _LIBCPP_CXX03_LANG49template <class _UnaryOperation>50_LIBCPP_HIDE_FROM_ABI param_type(initializer_list<result_type> __bl, _UnaryOperation __fw);51#endif // _LIBCPP_CXX03_LANG52template <class _UnaryOperation>53_LIBCPP_HIDE_FROM_ABI param_type(size_t __nw, result_type __xmin, result_type __xmax, _UnaryOperation __fw);54_LIBCPP_HIDE_FROM_ABI param_type(param_type const&) = default;55_LIBCPP_HIDE_FROM_ABI param_type& operator=(const param_type& __rhs);5657_LIBCPP_HIDE_FROM_ABI vector<result_type> intervals() const { return __b_; }58_LIBCPP_HIDE_FROM_ABI vector<result_type> densities() const { return __densities_; }5960friend _LIBCPP_HIDE_FROM_ABI bool operator==(const param_type& __x, const param_type& __y) {61return __x.__densities_ == __y.__densities_ && __x.__b_ == __y.__b_;62}63friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const param_type& __x, const param_type& __y) { return !(__x == __y); }6465private:66_LIBCPP_HIDE_FROM_ABI void __init();6768friend class piecewise_linear_distribution;6970template <class _CharT, class _Traits, class _RT>71friend basic_ostream<_CharT, _Traits>&72operator<<(basic_ostream<_CharT, _Traits>& __os, const piecewise_linear_distribution<_RT>& __x);7374template <class _CharT, class _Traits, class _RT>75friend basic_istream<_CharT, _Traits>&76operator>>(basic_istream<_CharT, _Traits>& __is, piecewise_linear_distribution<_RT>& __x);77};7879private:80param_type __p_;8182public:83// constructor and reset functions84_LIBCPP_HIDE_FROM_ABI piecewise_linear_distribution() {}85template <class _InputIteratorB, class _InputIteratorW>86_LIBCPP_HIDE_FROM_ABI87piecewise_linear_distribution(_InputIteratorB __f_b, _InputIteratorB __l_b, _InputIteratorW __f_w)88: __p_(__f_b, __l_b, __f_w) {}8990#ifndef _LIBCPP_CXX03_LANG91template <class _UnaryOperation>92_LIBCPP_HIDE_FROM_ABI piecewise_linear_distribution(initializer_list<result_type> __bl, _UnaryOperation __fw)93: __p_(__bl, __fw) {}94#endif // _LIBCPP_CXX03_LANG9596template <class _UnaryOperation>97_LIBCPP_HIDE_FROM_ABI98piecewise_linear_distribution(size_t __nw, result_type __xmin, result_type __xmax, _UnaryOperation __fw)99: __p_(__nw, __xmin, __xmax, __fw) {}100101_LIBCPP_HIDE_FROM_ABI explicit piecewise_linear_distribution(const param_type& __p) : __p_(__p) {}102103_LIBCPP_HIDE_FROM_ABI void reset() {}104105// generating functions106template <class _URNG>107_LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g) {108return (*this)(__g, __p_);109}110template <class _URNG>111_LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p);112113// property functions114_LIBCPP_HIDE_FROM_ABI vector<result_type> intervals() const { return __p_.intervals(); }115_LIBCPP_HIDE_FROM_ABI vector<result_type> densities() const { return __p_.densities(); }116117_LIBCPP_HIDE_FROM_ABI param_type param() const { return __p_; }118_LIBCPP_HIDE_FROM_ABI void param(const param_type& __p) { __p_ = __p; }119120_LIBCPP_HIDE_FROM_ABI result_type min() const { return __p_.__b_.front(); }121_LIBCPP_HIDE_FROM_ABI result_type max() const { return __p_.__b_.back(); }122123friend _LIBCPP_HIDE_FROM_ABI bool124operator==(const piecewise_linear_distribution& __x, const piecewise_linear_distribution& __y) {125return __x.__p_ == __y.__p_;126}127friend _LIBCPP_HIDE_FROM_ABI bool128operator!=(const piecewise_linear_distribution& __x, const piecewise_linear_distribution& __y) {129return !(__x == __y);130}131132template <class _CharT, class _Traits, class _RT>133friend basic_ostream<_CharT, _Traits>&134operator<<(basic_ostream<_CharT, _Traits>& __os, const piecewise_linear_distribution<_RT>& __x);135136template <class _CharT, class _Traits, class _RT>137friend basic_istream<_CharT, _Traits>&138operator>>(basic_istream<_CharT, _Traits>& __is, piecewise_linear_distribution<_RT>& __x);139};140141template <class _RealType>142typename piecewise_linear_distribution<_RealType>::param_type&143piecewise_linear_distribution<_RealType>::param_type::operator=(const param_type& __rhs) {144// These can throw145__b_.reserve(__rhs.__b_.size());146__densities_.reserve(__rhs.__densities_.size());147__areas_.reserve(__rhs.__areas_.size());148149// These can not throw150__b_ = __rhs.__b_;151__densities_ = __rhs.__densities_;152__areas_ = __rhs.__areas_;153return *this;154}155156template <class _RealType>157void piecewise_linear_distribution<_RealType>::param_type::__init() {158__areas_.assign(__densities_.size() - 1, result_type());159result_type __sp = 0;160for (size_t __i = 0; __i < __areas_.size(); ++__i) {161__areas_[__i] = (__densities_[__i + 1] + __densities_[__i]) * (__b_[__i + 1] - __b_[__i]) * .5;162__sp += __areas_[__i];163}164for (size_t __i = __areas_.size(); __i > 1;) {165--__i;166__areas_[__i] = __areas_[__i - 1] / __sp;167}168__areas_[0] = 0;169for (size_t __i = 1; __i < __areas_.size(); ++__i)170__areas_[__i] += __areas_[__i - 1];171for (size_t __i = 0; __i < __densities_.size(); ++__i)172__densities_[__i] /= __sp;173}174175template <class _RealType>176piecewise_linear_distribution<_RealType>::param_type::param_type() : __b_(2), __densities_(2, 1.0), __areas_(1, 0.0) {177__b_[1] = 1;178}179180template <class _RealType>181template <class _InputIteratorB, class _InputIteratorW>182piecewise_linear_distribution<_RealType>::param_type::param_type(183_InputIteratorB __f_b, _InputIteratorB __l_b, _InputIteratorW __f_w)184: __b_(__f_b, __l_b) {185if (__b_.size() < 2) {186__b_.resize(2);187__b_[0] = 0;188__b_[1] = 1;189__densities_.assign(2, 1.0);190__areas_.assign(1, 0.0);191} else {192__densities_.reserve(__b_.size());193for (size_t __i = 0; __i < __b_.size(); ++__i, ++__f_w)194__densities_.push_back(*__f_w);195__init();196}197}198199#ifndef _LIBCPP_CXX03_LANG200201template <class _RealType>202template <class _UnaryOperation>203piecewise_linear_distribution<_RealType>::param_type::param_type(204initializer_list<result_type> __bl, _UnaryOperation __fw)205: __b_(__bl.begin(), __bl.end()) {206if (__b_.size() < 2) {207__b_.resize(2);208__b_[0] = 0;209__b_[1] = 1;210__densities_.assign(2, 1.0);211__areas_.assign(1, 0.0);212} else {213__densities_.reserve(__b_.size());214for (size_t __i = 0; __i < __b_.size(); ++__i)215__densities_.push_back(__fw(__b_[__i]));216__init();217}218}219220#endif // _LIBCPP_CXX03_LANG221222template <class _RealType>223template <class _UnaryOperation>224piecewise_linear_distribution<_RealType>::param_type::param_type(225size_t __nw, result_type __xmin, result_type __xmax, _UnaryOperation __fw)226: __b_(__nw == 0 ? 2 : __nw + 1) {227size_t __n = __b_.size() - 1;228result_type __d = (__xmax - __xmin) / __n;229__densities_.reserve(__b_.size());230for (size_t __i = 0; __i < __n; ++__i) {231__b_[__i] = __xmin + __i * __d;232__densities_.push_back(__fw(__b_[__i]));233}234__b_[__n] = __xmax;235__densities_.push_back(__fw(__b_[__n]));236__init();237}238239template <class _RealType>240template <class _URNG>241_RealType piecewise_linear_distribution<_RealType>::operator()(_URNG& __g, const param_type& __p) {242static_assert(__libcpp_random_is_valid_urng<_URNG>::value, "");243typedef uniform_real_distribution<result_type> _Gen;244result_type __u = _Gen()(__g);245ptrdiff_t __k = std::upper_bound(__p.__areas_.begin(), __p.__areas_.end(), __u) - __p.__areas_.begin() - 1;246__u -= __p.__areas_[__k];247const result_type __dk = __p.__densities_[__k];248const result_type __dk1 = __p.__densities_[__k + 1];249const result_type __deltad = __dk1 - __dk;250const result_type __bk = __p.__b_[__k];251if (__deltad == 0)252return __u / __dk + __bk;253const result_type __bk1 = __p.__b_[__k + 1];254const result_type __deltab = __bk1 - __bk;255return (__bk * __dk1 - __bk1 * __dk + std::sqrt(__deltab * (__deltab * __dk * __dk + 2 * __deltad * __u))) / __deltad;256}257258template <class _CharT, class _Traits, class _RT>259_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&260operator<<(basic_ostream<_CharT, _Traits>& __os, const piecewise_linear_distribution<_RT>& __x) {261__save_flags<_CharT, _Traits> __lx(__os);262typedef basic_ostream<_CharT, _Traits> _OStream;263__os.flags(_OStream::dec | _OStream::left | _OStream::fixed | _OStream::scientific);264_CharT __sp = __os.widen(' ');265__os.fill(__sp);266size_t __n = __x.__p_.__b_.size();267__os << __n;268for (size_t __i = 0; __i < __n; ++__i)269__os << __sp << __x.__p_.__b_[__i];270__n = __x.__p_.__densities_.size();271__os << __sp << __n;272for (size_t __i = 0; __i < __n; ++__i)273__os << __sp << __x.__p_.__densities_[__i];274__n = __x.__p_.__areas_.size();275__os << __sp << __n;276for (size_t __i = 0; __i < __n; ++__i)277__os << __sp << __x.__p_.__areas_[__i];278return __os;279}280281template <class _CharT, class _Traits, class _RT>282_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&283operator>>(basic_istream<_CharT, _Traits>& __is, piecewise_linear_distribution<_RT>& __x) {284typedef piecewise_linear_distribution<_RT> _Eng;285typedef typename _Eng::result_type result_type;286__save_flags<_CharT, _Traits> __lx(__is);287typedef basic_istream<_CharT, _Traits> _Istream;288__is.flags(_Istream::dec | _Istream::skipws);289size_t __n;290__is >> __n;291vector<result_type> __b(__n);292for (size_t __i = 0; __i < __n; ++__i)293__is >> __b[__i];294__is >> __n;295vector<result_type> __densities(__n);296for (size_t __i = 0; __i < __n; ++__i)297__is >> __densities[__i];298__is >> __n;299vector<result_type> __areas(__n);300for (size_t __i = 0; __i < __n; ++__i)301__is >> __areas[__i];302if (!__is.fail()) {303swap(__x.__p_.__b_, __b);304swap(__x.__p_.__densities_, __densities);305swap(__x.__p_.__areas_, __areas);306}307return __is;308}309310_LIBCPP_END_NAMESPACE_STD311312_LIBCPP_POP_MACROS313314#endif // _LIBCPP___RANDOM_PIECEWISE_LINEAR_DISTRIBUTION_H315316317