1 /* boost random/fisher_f_distribution.hpp header file
2  *
3  * Copyright Steven Watanabe 2011
4  * Distributed under the Boost Software License, Version 1.0. (See
5  * accompanying file LICENSE_1_0.txt or copy at
6  * http://www.boost.org/LICENSE_1_0.txt)
7  *
8  * See http://www.boost.org for most recent version including documentation.
9  *
10  * $Id$
11  */
12 
13 #ifndef BOOST_RANDOM_FISHER_F_DISTRIBUTION_HPP
14 #define BOOST_RANDOM_FISHER_F_DISTRIBUTION_HPP
15 
16 #include <iosfwd>
17 #include <istream>
18 #include <boost/config.hpp>
19 #include <boost/limits.hpp>
20 #include <boost/random/detail/operators.hpp>
21 #include <boost/random/chi_squared_distribution.hpp>
22 
23 namespace boost {
24 namespace random {
25 
26 /**
27  * The Fisher F distribution is a real valued distribution with two
28  * parameters m and n.
29  *
30  * It has \f$\displaystyle p(x) =
31  *   \frac{\Gamma((m+n)/2)}{\Gamma(m/2)\Gamma(n/2)}
32  *   \left(\frac{m}{n}\right)^{m/2}
33  *   x^{(m/2)-1} \left(1+\frac{mx}{n}\right)^{-(m+n)/2}
34  * \f$.
35  */
36 template<class RealType = double>
37 class fisher_f_distribution {
38 public:
39     typedef RealType result_type;
40     typedef RealType input_type;
41 
42     class param_type {
43     public:
44         typedef fisher_f_distribution distribution_type;
45 
46         /**
47          * Constructs a @c param_type from the "m" and "n" parameters
48          * of the distribution.
49          *
50          * Requires: m > 0 and n > 0
51          */
param_type(RealType m_arg=RealType (1.0),RealType n_arg=RealType (1.0))52         explicit param_type(RealType m_arg = RealType(1.0),
53                             RealType n_arg = RealType(1.0))
54           : _m(m_arg), _n(n_arg)
55         {}
56 
57         /** Returns the "m" parameter of the distribtuion. */
m() const58         RealType m() const { return _m; }
59         /** Returns the "n" parameter of the distribution. */
n() const60         RealType n() const { return _n; }
61 
62         /** Writes a @c param_type to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os,param_type,parm)63         BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
64         { os << parm._m << ' ' << parm._n; return os; }
65 
66         /** Reads a @c param_type from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is,param_type,parm)67         BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
68         { is >> parm._m >> std::ws >> parm._n; return is; }
69 
70         /** Returns true if the two sets of parameters are the same. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type,lhs,rhs)71         BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
72         { return lhs._m == rhs._m && lhs._n == rhs._n; }
73 
74         /** Returns true if the two sets of parameters are the different. */
75         BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
76 
77     private:
78         RealType _m;
79         RealType _n;
80     };
81 
82     /**
83      * Constructs a @c fisher_f_distribution from its "m" and "n" parameters.
84      *
85      * Requires: m > 0 and n > 0
86      */
fisher_f_distribution(RealType m_arg=RealType (1.0),RealType n_arg=RealType (1.0))87     explicit fisher_f_distribution(RealType m_arg = RealType(1.0),
88                                    RealType n_arg = RealType(1.0))
89       : _impl_m(m_arg), _impl_n(n_arg)
90     {}
91     /** Constructs an @c fisher_f_distribution from its parameters. */
fisher_f_distribution(const param_type & parm)92     explicit fisher_f_distribution(const param_type& parm)
93       : _impl_m(parm.m()), _impl_n(parm.n())
94     {}
95 
96     /**
97      * Returns a random variate distributed according to the
98      * F distribution.
99      */
100     template<class URNG>
operator ()(URNG & urng)101     RealType operator()(URNG& urng)
102     {
103         return (_impl_m(urng) * n()) / (_impl_n(urng) * m());
104     }
105 
106     /**
107      * Returns a random variate distributed according to the
108      * F distribution with parameters specified by @c param.
109      */
110     template<class URNG>
operator ()(URNG & urng,const param_type & parm) const111     RealType operator()(URNG& urng, const param_type& parm) const
112     {
113         return fisher_f_distribution(parm)(urng);
114     }
115 
116     /** Returns the "m" parameter of the distribution. */
m() const117     RealType m() const { return _impl_m.n(); }
118     /** Returns the "n" parameter of the distribution. */
n() const119     RealType n() const { return _impl_n.n(); }
120 
121     /** Returns the smallest value that the distribution can produce. */
BOOST_PREVENT_MACRO_SUBSTITUTION() const122     RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; }
123     /** Returns the largest value that the distribution can produce. */
BOOST_PREVENT_MACRO_SUBSTITUTION() const124     RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
125     { return std::numeric_limits<RealType>::infinity(); }
126 
127     /** Returns the parameters of the distribution. */
param() const128     param_type param() const { return param_type(m(), n()); }
129     /** Sets the parameters of the distribution. */
param(const param_type & parm)130     void param(const param_type& parm)
131     {
132         typedef chi_squared_distribution<RealType> impl_type;
133         typename impl_type::param_type m_param(parm.m());
134         _impl_m.param(m_param);
135         typename impl_type::param_type n_param(parm.n());
136         _impl_n.param(n_param);
137     }
138 
139     /**
140      * Effects: Subsequent uses of the distribution do not depend
141      * on values produced by any engine prior to invoking reset.
142      */
reset()143     void reset() { }
144 
145     /** Writes an @c fisher_f_distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os,fisher_f_distribution,fd)146     BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, fisher_f_distribution, fd)
147     {
148         os << fd.param();
149         return os;
150     }
151 
152     /** Reads an @c fisher_f_distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is,fisher_f_distribution,fd)153     BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, fisher_f_distribution, fd)
154     {
155         param_type parm;
156         if(is >> parm) {
157             fd.param(parm);
158         }
159         return is;
160     }
161 
162     /**
163      * Returns true if the two instances of @c fisher_f_distribution will
164      * return identical sequences of values given equal generators.
165      */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(fisher_f_distribution,lhs,rhs)166     BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(fisher_f_distribution, lhs, rhs)
167     { return lhs._impl_m == rhs._impl_m && lhs._impl_n == rhs._impl_n; }
168 
169     /**
170      * Returns true if the two instances of @c fisher_f_distribution will
171      * return different sequences of values given equal generators.
172      */
173     BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(fisher_f_distribution)
174 
175 private:
176     chi_squared_distribution<RealType> _impl_m;
177     chi_squared_distribution<RealType> _impl_n;
178 };
179 
180 } // namespace random
181 } // namespace boost
182 
183 #endif // BOOST_RANDOM_EXTREME_VALUE_DISTRIBUTION_HPP
184