source: mainline/uspace/lib/cpp/include/impl/random.hpp@ 6b81ca5

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6b81ca5 was e7a4f41, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added subtract_with_carry_engine

  • Property mode set to 100644
File size: 25.8 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_RANDOM
30#define LIBCPP_RANDOM
31
32#include <cstdlib>
33#include <ctime>
34#include <initializer_list>
35#include <internal/builtins.hpp>
36#include <limits>
37#include <type_traits>
38#include <vector>
39
40/**
41 * Note: Variables with one or two lettered
42 * names here are named after their counterparts in
43 * the standard. If one needs to understand their meaning,
44 * they should seek the mentioned standard section near
45 * the declaration of these variables.
46 * Note: There will be a lot of mathematical expressions in this header.
47 * All of these are taken directly from the standard's requirements
48 * and as such won't be commented here, check the appropriate
49 * sections if you need explanation of these forumulae.
50 */
51
52namespace std
53{
54 namespace aux
55 {
56 /**
57 * This is the minimum requirement imposed by the
58 * standard for a type to qualify as a seed sequence
59 * in overloading resolutions.
60 * (This is because the engines have constructors
61 * that accept sequence and seed and without this
62 * minimal requirements overload resolution would fail.)
63 */
64 template<class Sequence, class ResultType>
65 struct is_seed_sequence
66 : aux::value_is<
67 bool, !is_convertible_v<Sequence, ResultType>
68 >
69 { /* DUMMY BODY */ };
70
71 template<class T, class Engine>
72 inline constexpr bool is_seed_sequence_v = is_seed_sequence<T, Engine>::value;
73 }
74
75 /**
76 * 26.5.3.1, class template linear_congruential_engine:
77 */
78
79 template<class UIntType, UIntType a, UIntType c, UIntType m>
80 class linear_congruential_engine
81 {
82 static_assert(m == 0 || (a < m && c < m));
83
84 public:
85 using result_type = UIntType;
86
87 static constexpr result_type multiplier = a;
88 static constexpr result_type increment = c;
89 static constexpr result_type modulus = m;
90
91 static constexpr result_type min()
92 {
93 return c == 0U ? 1U : 0U;
94 }
95
96 static constexpr result_type max()
97 {
98 return m - 1U;
99 }
100
101 static constexpr result_type default_seed = 1U;
102
103 explicit linear_congruential_engine(result_type s = default_seed)
104 : state_{}
105 {
106 seed(s);
107 }
108
109 linear_congruential_engine(const linear_congruential_engine& other)
110 : state_{other.state_}
111 { /* DUMMY BODY */ }
112
113 template<class Seq>
114 explicit linear_congruential_engine(
115 enable_if_t<aux::is_seed_sequence_v<Seq, result_type>, Seq&> q
116 )
117 : state_{}
118 {
119 seed(q);
120 }
121
122 void seed(result_type s = default_seed)
123 {
124 if (c % modulus_ == 0 && s == 0)
125 state_ = 0;
126 else
127 state_ = s;
128 }
129
130 template<class Seq>
131 void seed(
132 enable_if_t<aux::is_seed_sequence_v<Seq, result_type>, Seq&> q
133 )
134 {
135 q.generate(arr_, arr_ + k_ + 3);
136
137 result_type s{};
138 for (size_t j = 0; j < k_; ++j)
139 s += arr_[j + 3] * aux::pow2(32U * j);
140 s = s % modulus_;
141
142 seed(s);
143 }
144
145 result_type operator()()
146 {
147 return generate_();
148 }
149
150 void discard(unsigned long long z)
151 {
152 for (unsigned long long i = 0ULL; i < z; ++i)
153 transition_();
154 }
155
156 bool operator==(const linear_congruential_engine& rhs) const
157 {
158 return state_ = rhs.state_;
159 }
160
161 bool operator!=(const linear_congruential_engine& rhs) const
162 {
163 return !(*this == rhs);
164 }
165
166 template<class Char, class Traits>
167 basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os) const
168 {
169 auto flags = os.flags();
170 os.flags(ios_base::dec | ios_base::left);
171
172 os << state_;
173
174 os.flags(flags);
175 return os;
176 }
177
178 template<class Char, class Traits>
179 basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is) const
180 {
181 auto flags = is.flags();
182 is.flags(ios_base::dec);
183
184 result_type tmp{};
185 if (is >> tmp)
186 state_ = tmp;
187 else
188 is.setstate(ios::failbit);
189
190 is.flags(flags);
191 return is;
192 }
193
194 private:
195 result_type state_;
196
197 static constexpr result_type modulus_ =
198 (m == 0) ? (numeric_limits<result_type>::max() + 1) : m;
199
200 /**
201 * We use constexpr builtins to keep this array
202 * between calls to seed(Seq&), which means we don't
203 * have to keep allocating and deleting it.
204 */
205 static constexpr size_t k_ = static_cast<size_t>(aux::ceil(aux::log2(modulus_) / 32));
206 result_type arr_[k_ + 3];
207
208 void transition_()
209 {
210 state_ = (a * state_ + c) % modulus_;
211 }
212
213 result_type generate_()
214 {
215 transition_();
216
217 return state_;
218 }
219 };
220
221 /**
222 * 26.5.3.2, class template mersenne_twister_engine:
223 */
224
225 template<
226 class UIntType, size_t w, size_t n, size_t m, size_t r,
227 UIntType a, size_t u, UIntType d, size_t s,
228 UIntType b, size_t t, UIntType c, size_t l, UIntType f
229 >
230 class mersenne_twister_engine
231 {
232 // TODO: fix these
233 /* static_assert(0 < m && m <= n); */
234 /* static_assert(2 * u < w); */
235 /* static_assert(r <= w && u <= w && s <= w && t <= w && l <= w); */
236 /* /1* static_assert(w <= numeric_limits<UIntType>::digits); *1/ */
237 /* static_assert(a <= (1U << w) - 1U); */
238 /* static_assert(b <= (1U << w) - 1U); */
239 /* static_assert(c <= (1U << w) - 1U); */
240 /* static_assert(d <= (1U << w) - 1U); */
241 /* static_assert(f <= (1U << w) - 1U); */
242
243 public:
244 using result_type = UIntType;
245
246 static constexpr size_t word_size = w;
247 static constexpr size_t state_size = n;
248 static constexpr size_t shift_size = m;
249 static constexpr size_t mask_bits = r;
250 static constexpr UIntType xor_mask = a;
251
252 static constexpr size_t tempering_u = u;
253 static constexpr UIntType tempering_d = d;
254 static constexpr size_t tempering_s = s;
255 static constexpr UIntType tempering_b = b;
256 static constexpr size_t tempering_t = t;
257 static constexpr UIntType tempering_c = c;
258 static constexpr size_t tempering_l = l;
259
260 static constexpr UIntType initialization_multiplier = f;
261
262 static constexpr result_type min()
263 {
264 return result_type{};
265 }
266
267 static constexpr result_type max()
268 {
269 return static_cast<result_type>(aux::pow2(w)) - 1U;
270 }
271
272 static constexpr result_type default_seed = 5489U;
273
274 explicit mersenne_twister_engine(result_type value = default_seed)
275 : state_{}, i_{}
276 {
277 seed(value);
278 }
279
280 template<class Seq>
281 explicit mersenne_twister_engine(
282 enable_if_t<aux::is_seed_sequence_v<Seq, result_type>, Seq&> q
283 )
284 : state_{}, i_{}
285 {
286 seed(q);
287 }
288
289 void seed(result_type value = default_seed)
290 {
291 state_[idx_(-n)] = value % aux::pow2u(w);;
292
293 for (long long i = 1 - n; i <= -1; ++i)
294 {
295 state_[idx_(i)] = (f * (state_[idx_(i - 1)] ^
296 (state_[idx_(i - 1)] >> (w - 2))) + 1 % n) % aux::pow2u(w);
297 }
298 }
299
300 template<class Seq>
301 void seed(
302 enable_if_t<aux::is_seed_sequence_v<Seq, result_type>, Seq&> q
303 )
304 {
305 q.generate(arr_, arr_ + n * k_);
306
307 for (long long i = -n; i <= -1; ++i)
308 {
309 state_[idx_(i)] = result_type{};
310 for (long long j = 0; j < k_; ++j)
311 state_[idx_(i)] += arr_[k_ * (i + n) + j] * aux::pow2(32 * j);
312 state_[idx_(i)] %= aux::pow2(w);
313 }
314 }
315
316 result_type operator()()
317 {
318 return generate_();
319 }
320
321 void discard(unsigned long long z)
322 {
323 for (unsigned long long i = 0ULL; i < z; ++i)
324 transition_();
325 }
326
327 bool operator==(const mersenne_twister_engine& rhs) const
328 {
329 for (size_t i = 0; i < n; ++i)
330 {
331 if (state_[i] != rhs.state_[i])
332 return false;
333 }
334
335 return true;
336 }
337
338 bool operator!=(const mersenne_twister_engine& rhs) const
339 {
340 return !(*this == rhs);
341 }
342
343 template<class Char, class Traits>
344 basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os) const
345 {
346 auto flags = os.flags();
347 os.flags(ios_base::dec | ios_base::left);
348
349 for (size_t j = n + 1; j > 1; --j)
350 {
351 os << state_[idx_(i_ - j - 1)];
352
353 if (j > 2)
354 os << os.widen(' ');
355 }
356
357 os.flags(flags);
358 return os;
359 }
360
361 template<class Char, class Traits>
362 basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is) const
363 {
364 auto flags = is.flags();
365 is.flags(ios_base::dec);
366
367 for (size_t j = n + 1; j > 1; --j)
368 {
369 if (!(is >> state_[idx_(i_ - j - 1)]))
370 {
371 is.setstate(ios::failbit);
372 break;
373 }
374 }
375
376 is.flags(flags);
377 return is;
378 }
379
380 private:
381 result_type state_[n];
382 size_t i_;
383
384 static constexpr size_t k_ = static_cast<size_t>(w / 32);
385 result_type arr_[n * k_];
386
387 void transition_()
388 {
389 auto mask = (result_type{1} << r) - 1;
390 auto y = (state_[idx_(i_ - n)] & ~mask) | (state_[idx_(i_ + 1 - n)] & mask);
391 auto alpha = a * (y & 1);
392 state_[i_] = state_[idx_(i_ + m - n)] ^ (y >> 1) ^ alpha;
393
394 i_ = (i_ + 1) % n;
395 }
396
397 result_type generate_()
398 {
399 auto z1 = state_[i_] ^ ((state_[i_] >> u) & d);
400 auto z2 = z1 ^ (lshift_(z1, s) & b);
401 auto z3 = z2 ^ (lshift_(z2, t) & c);
402 auto z4 = z3 ^ (z3 >> l);
403
404 transition_();
405
406 return z4;
407 }
408
409 size_t idx_(size_t idx) const
410 {
411 return idx % n;
412 }
413
414 result_type lshift_(result_type val, size_t count)
415 {
416 return (val << count) % aux::pow2u(w);
417 }
418 };
419
420 /**
421 * 26.5.3.3, class template subtract_with_carry_engine:
422 */
423
424 template<class UIntType, size_t w, size_t s, size_t r>
425 class subtract_with_carry_engine
426 {
427 // TODO: fix these
428 /* static_assert(0U < s); */
429 /* static_assert(s < r); */
430 /* static_assert(0U < w); */
431 /* static_assert(w <= numeric_limits<UIntType>::digits); */
432
433 public:
434 using result_type = UIntType;
435
436 static constexpr size_t word_size = w;
437 static constexpr size_t short_lag = s;
438 static constexpr size_t long_lag = r;
439
440 static constexpr result_type min()
441 {
442 return result_type{};
443 }
444
445 static constexpr result_type max()
446 {
447 return m_ - 1;
448 }
449
450 static constexpr result_type default_seed = 19780503U;
451
452 explicit subtract_with_carry_engine(result_type value = default_seed)
453 : state_{}, i_{}, carry_{}
454 {
455 seed(value);
456 }
457
458 template<class Seq>
459 explicit subtract_with_carry_engine(
460 enable_if_t<aux::is_seed_sequence_v<Seq, result_type>, Seq&> q
461 )
462 : state_{}, i_{}, carry_{}
463 {
464 seed(q);
465 }
466
467 void seed(result_type value = default_seed)
468 {
469 linear_congruential_engine<
470 result_type, 40014U, 0U, 2147483563U
471 > e{value == 0U ? default_seed : value};
472
473 auto n = aux::ceil(w / 32.0);
474 auto z = new result_type[n];
475
476 for (long long i = -r; i <= -1; ++i)
477 {
478 for (size_t i = 0; i < n; ++i)
479 z[i] = e() % aux::pow2u(32);
480
481 state_[idx_(i)] = result_type{};
482 for (size_t j = 0; j < n; ++j)
483 state_[idx_(i)] += z[j] * aux::pow2u(32 * j);
484 state_[idx_(i)] %= m_;
485 }
486
487 if (state_[idx_(-1)] == 0)
488 carry_ = 1;
489 else
490 carry_ = 0;
491
492 delete[] z;
493 }
494
495 template<class Seq>
496 void seed(
497 enable_if_t<aux::is_seed_sequence_v<Seq, result_type>, Seq&> q
498 )
499 {
500 auto k = aux::ceil(w / 32.0);
501 auto arr = new result_type[r * k];
502
503 q.generate(arr, arr + r * k);
504
505 for (long long i = -r; i <= -1; ++i)
506 {
507 state_[idx_(i)] = result_type{};
508 for (long long j = 0; j < k; ++j)
509 state_[idx_(i)] += arr[k * (i + r) + j] * aux::pow2(32 * j);
510 state_[idx_(i)] %= m_;
511 }
512
513 delete[] arr;
514
515 if (state_[idx_(-1)] == 0)
516 carry_ = 1;
517 else
518 carry_ = 0;
519 }
520
521 result_type operator()()
522 {
523 return generate_();
524 }
525
526 void discard(unsigned long long z)
527 {
528 for (unsigned long long i = 0ULL; i < z; ++i)
529 transition_();
530 }
531
532 bool operator==(const subtract_with_carry_engine& rhs) const
533 {
534 for (size_t i = 0; i < r; ++i)
535 {
536 if (state_[i] != rhs.state_[i])
537 return false;
538 }
539
540 return true;
541 }
542
543 bool operator!=(const subtract_with_carry_engine& rhs) const
544 {
545 return !(*this == rhs);
546 }
547
548 template<class Char, class Traits>
549 basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os) const
550 {
551 auto flags = os.flags();
552 os.flags(ios_base::dec | ios_base::left);
553
554 for (size_t j = r + 1; j > 1; --j)
555 {
556 os << state_[idx_(i_ - j - 1)];
557 os << os.widen(' ');
558 }
559
560 os << carry_;
561
562 os.flags(flags);
563 return os;
564 }
565
566 template<class Char, class Traits>
567 basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is) const
568 {
569 auto flags = is.flags();
570 is.flags(ios_base::dec);
571
572 for (size_t j = r + 1; j > 1; --j)
573 {
574 if (!(is >> state_[idx_(i_ - j - 1)]))
575 {
576 is.setstate(ios::failbit);
577 break;
578 }
579 }
580
581 if (!(is >> carry_))
582 is.setstate(ios::failbit);
583
584 is.flags(flags);
585 return is;
586 }
587
588 private:
589 result_type state_[r];
590 size_t i_;
591 uint8_t carry_;
592
593 static constexpr result_type m_ = aux::pow2u(w);
594
595 auto transition_()
596 {
597 auto y = static_cast<int64_t>(state_[idx_(i_ - s)]) - state_[idx_(i_ - r)] - carry_;
598 state_[i_] = y % m_;
599
600 i_ = (i_ + 1) % r;
601
602 return static_cast<result_type>(y % m_);
603 }
604
605 result_type generate_()
606 {
607 return transition_();
608 }
609
610 size_t idx_(size_t idx) const
611 {
612 return idx % r;
613 }
614 };
615
616 /**
617 * 26.5.4.2, class template discard_block_engine:
618 */
619
620 template<class Engine, size_t p, size_t r>
621 class discard_block_engine;
622
623 /**
624 * 26.5.4.3, class template independent_bits_engine:
625 */
626
627 template<class Engine, size_t w, class UIntType>
628 class independent_bits_engine;
629
630 /**
631 * 26.5.4.4, class template shiffle_order_engine:
632 */
633
634 template<class Engine, size_t k>
635 class shuffle_order_engine;
636
637 /**
638 * 26.5.5, engines and engine adaptors with predefined
639 * parameters:
640 * TODO: check their requirements for testing
641 */
642
643 using minstd_rand0 = linear_congruential_engine<uint_fast32_t, 16807, 0, 2147483647>;
644 using minstd_rand = linear_congruential_engine<uint_fast32_t, 48271, 0, 2147483647>;
645 using mt19937 = mersenne_twister_engine<
646 uint_fast32_t, 32, 624, 397, 31, 0x9908b0df, 11, 0xffffffff, 7,
647 0x9d2c5680, 15, 0xefc60000, 18, 1812433253
648 >;
649 using mt19937_64 = mersenne_twister_engine<
650 uint_fast64_t, 64, 312, 156, 31, 0xb5026f5aa96619e9, 29,
651 0x5555555555555555, 17, 0x71d67fffeda60000, 37, 0xfff7eee000000000,
652 43, 6364136223846793005
653 >;
654 using ranlux24_base = subtract_with_carry_engine<uint_fast32_t, 24, 10, 24>;
655 using ranlux48_base = subtract_with_carry_engine<uint_fast64_t, 48, 5, 12>;
656 using ranlux24 = discard_block_engine<ranlux24_base, 223, 23>;
657 using ranlux48 = discard_block_engine<ranlux48_base, 389, 11>;
658 using knuth_b = shuffle_order_engine<minstd_rand0, 256>;
659
660 using default_random_engine = minstd_rand0;
661
662 /**
663 * 26.5.6, class random_device:
664 */
665
666 class random_device
667 {
668 using result_type = unsigned int;
669
670 static constexpr result_type min()
671 {
672 return numeric_limits<result_type>::min();
673 }
674
675 static constexpr result_type max()
676 {
677 return numeric_limits<result_type>::max();
678 }
679
680 explicit random_device(const string& token = "")
681 {
682 /**
683 * Note: token can be used to choose between
684 * random generators, but HelenOS only
685 * has one :/
686 * Also note that it is implementation
687 * defined how this class generates
688 * random numbers and I decided to use
689 * time seeding with C stdlib random,
690 * - feel free to change it if you know
691 * something better.
692 */
693 hel::srandom(hel::time(nullptr));
694 }
695
696 result_type operator()()
697 {
698 return hel::random();
699 }
700
701 double entropy() const noexcept
702 {
703 return 0.0;
704 }
705
706 random_device(const random_device&) = delete;
707 random_device& operator=(const random_device&) = delete;
708 };
709
710 /**
711 * 26.5.7.1, class seed_seq:
712 */
713
714 class seed_seq
715 {
716 public:
717 using result_type = uint_least32_t;
718
719 seed_seq()
720 : vec_{}
721 { /* DUMMY BODY */ }
722
723 template<class T>
724 seed_seq(initializer_list<T> init)
725 : seed_seq(init.begin(), init.end())
726 { /* DUMMY BODY */ }
727
728 template<class InputIterator>
729 seed_seq(InputIterator first, InputIterator last)
730 : vec_{}
731 {
732 while (first != last)
733 vec_.push_back(*first++ % aux::pow2(32));
734 }
735
736 template<class RandomAccessGenerator>
737 void generate(RandomAccessGenerator first,
738 RandomAccessGenerator last)
739 {
740 if (first == last)
741 return;
742
743 // TODO: research this
744 }
745
746 size_t size() const
747 {
748 return vec_.size();
749 }
750
751 template<class OutputIterator>
752 void param(OutputIterator dest) const
753 {
754 for (const auto& x: vec_)
755 *dest++ = x;
756 }
757
758 seed_seq(const seed_seq&) = delete;
759 seed_seq& operator=(const seed_seq&) = delete;
760
761 private:
762 vector<result_type> vec_;
763 };
764
765 /**
766 * 26.5.7.2, function template generate_canonical:
767 */
768
769 template<class RealType, size_t bits, class URNG>
770 RealType generate_canonical(URNG& g);
771
772 /**
773 * 26.5.8.2.1, class template uniform_int_distribution:
774 */
775
776 template<class IntType = int>
777 class uniform_int_distribution;
778
779 /**
780 * 26.5.8.2.2, class template uniform_real_distribution:
781 */
782
783 template<class RealType = double>
784 class uniform_real_distribution;
785
786 /**
787 * 26.5.8.3.1, class bernoulli_distribution:
788 */
789
790 class bernoulli_distribution;
791
792 /**
793 * 26.5.8.3.2, class template binomial_distribution:
794 */
795
796 template<class IntType = int>
797 class binomial_distribution;
798
799 /**
800 * 26.5.8.3.3, class template geometric_distribution:
801 */
802
803 template<class IntType = int>
804 class geometric_distribution;
805
806 /**
807 * 26.5.8.3.4, class template negative_binomial_distribution:
808 */
809
810 template<class IntType = int>
811 class negative_binomial_distribution;
812
813 /**
814 * 26.5.8.4.1, class template poisson_distribution:
815 */
816
817 template<class IntType = int>
818 class poisson_distribution;
819
820 /**
821 * 26.5.8.4.2, class template exponential_distribution:
822 */
823
824 template<class RealType = double>
825 class exponential_distribution;
826
827 /**
828 * 26.5.8.4.3, class template gamma_distribution:
829 */
830
831 template<class RealType = double>
832 class gamma_distribution;
833
834 /**
835 * 26.5.8.4.4, class template weibull_distribution:
836 */
837
838 template<class RealType = double>
839 class weibull_distribution;
840
841 /**
842 * 26.5.8.4.5, class template extreme_value_distribution:
843 */
844
845 template<class RealType = double>
846 class extreme_value_distribution;
847
848 /**
849 * 26.5.8.5.1, class template normal_distribution:
850 */
851
852 template<class RealType = double>
853 class normal_distribution;
854
855 /**
856 * 26.5.8.5.2, class template lognormal_distribution:
857 */
858
859 template<class RealType = double>
860 class lognormal_distribution;
861
862 /**
863 * 26.5.8.5.3, class template chi_squared_distribution:
864 */
865
866 template<class RealType = double>
867 class chi_squared_distribution;
868
869 /**
870 * 26.5.8.5.4, class template cauchy_distribution:
871 */
872
873 template<class RealType = double>
874 class cauchy_distribution;
875
876 /**
877 * 26.5.8.5.5, class template fisher_f_distribution:
878 */
879
880 template<class RealType = double>
881 class fisher_f_distribution;
882
883 /**
884 * 26.5.8.5.6, class template student_t_distribution:
885 */
886
887 template<class RealType = double>
888 class student_t_distribution;
889
890 /**
891 * 26.5.8.6.1, class template discrete_distribution:
892 */
893
894 template<class IntType = int>
895 class discrete_distribution;
896
897 /**
898 * 26.5.8.6.2, class template piecewise_constant_distribution:
899 */
900
901 template<class RealType = double>
902 class piecewise_constant_distribution;
903
904 /**
905 * 26.5.8.6.3, class template piecewise_linear_distribution:
906 */
907
908 template<class RealType = double>
909 class piecewise_linear_distribution;
910}
911
912#endif
Note: See TracBrowser for help on using the repository browser.