1 //  Copyright John Maddock 2006.
2 //  Copyright Paul A. Bristow 2006.
3 //  Use, modification and distribution are subject to the
4 //  Boost Software License, Version 1.0. (See accompanying file
5 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 // TODO deal with infinity as special better - or remove.
8 //
9 
10 #ifndef BOOST_STATS_UNIFORM_HPP
11 #define BOOST_STATS_UNIFORM_HPP
12 
13 // http://www.itl.nist.gov/div898/handbook/eda/section3/eda3668.htm
14 // http://mathworld.wolfram.com/UniformDistribution.html
15 // http://documents.wolfram.com/calculationcenter/v2/Functions/ListsMatrices/Statistics/UniformDistribution.html
16 // http://en.wikipedia.org/wiki/Uniform_distribution_%28continuous%29
17 
18 #include <boost/math/distributions/fwd.hpp>
19 #include <boost/math/distributions/detail/common_error_handling.hpp>
20 #include <boost/math/distributions/complement.hpp>
21 
22 #include <utility>
23 
24 namespace boost{ namespace math
25 {
26   namespace detail
27   {
28     template <class RealType, class Policy>
check_uniform_lower(const char * function,RealType lower,RealType * result,const Policy & pol)29     inline bool check_uniform_lower(
30       const char* function,
31       RealType lower,
32       RealType* result, const Policy& pol)
33     {
34       if((boost::math::isfinite)(lower))
35       { // any finite value is OK.
36         return true;
37       }
38       else
39       { // Not finite.
40         *result = policies::raise_domain_error<RealType>(
41           function,
42           "Lower parameter is %1%, but must be finite!", lower, pol);
43         return false;
44       }
45     } // bool check_uniform_lower(
46 
47     template <class RealType, class Policy>
check_uniform_upper(const char * function,RealType upper,RealType * result,const Policy & pol)48     inline bool check_uniform_upper(
49       const char* function,
50       RealType upper,
51       RealType* result, const Policy& pol)
52     {
53       if((boost::math::isfinite)(upper))
54       { // Any finite value is OK.
55         return true;
56       }
57       else
58       { // Not finite.
59         *result = policies::raise_domain_error<RealType>(
60           function,
61           "Upper parameter is %1%, but must be finite!", upper, pol);
62         return false;
63       }
64     } // bool check_uniform_upper(
65 
66     template <class RealType, class Policy>
check_uniform_x(const char * function,RealType const & x,RealType * result,const Policy & pol)67     inline bool check_uniform_x(
68       const char* function,
69       RealType const& x,
70       RealType* result, const Policy& pol)
71     {
72       if((boost::math::isfinite)(x))
73       { // Any finite value is OK
74         return true;
75       }
76       else
77       { // Not finite..
78         *result = policies::raise_domain_error<RealType>(
79           function,
80           "x parameter is %1%, but must be finite!", x, pol);
81         return false;
82       }
83     } // bool check_uniform_x
84 
85     template <class RealType, class Policy>
check_uniform(const char * function,RealType lower,RealType upper,RealType * result,const Policy & pol)86     inline bool check_uniform(
87       const char* function,
88       RealType lower,
89       RealType upper,
90       RealType* result, const Policy& pol)
91     {
92       if((check_uniform_lower(function, lower, result, pol) == false)
93         || (check_uniform_upper(function, upper, result, pol) == false))
94       {
95         return false;
96       }
97       else if (lower >= upper) // If lower == upper then 1 / (upper-lower) = 1/0 = +infinity!
98       { // upper and lower have been checked before, so must be lower >= upper.
99         *result = policies::raise_domain_error<RealType>(
100           function,
101           "lower parameter is %1%, but must be less than upper!", lower, pol);
102         return false;
103       }
104       else
105       { // All OK,
106         return true;
107       }
108     } // bool check_uniform(
109 
110   } // namespace detail
111 
112   template <class RealType = double, class Policy = policies::policy<> >
113   class uniform_distribution
114   {
115   public:
116     typedef RealType value_type;
117     typedef Policy policy_type;
118 
uniform_distribution(RealType l_lower=0,RealType l_upper=1)119     uniform_distribution(RealType l_lower = 0, RealType l_upper = 1) // Constructor.
120       : m_lower(l_lower), m_upper(l_upper) // Default is standard uniform distribution.
121     {
122       RealType result;
123       detail::check_uniform("boost::math::uniform_distribution<%1%>::uniform_distribution", l_lower, l_upper, &result, Policy());
124     }
125     // Accessor functions.
lower() const126     RealType lower()const
127     {
128       return m_lower;
129     }
130 
upper() const131     RealType upper()const
132     {
133       return m_upper;
134     }
135   private:
136     // Data members:
137     RealType m_lower;  // distribution lower aka a.
138     RealType m_upper;  // distribution upper aka b.
139   }; // class uniform_distribution
140 
141   typedef uniform_distribution<double> uniform;
142 
143   template <class RealType, class Policy>
range(const uniform_distribution<RealType,Policy> &)144   inline const std::pair<RealType, RealType> range(const uniform_distribution<RealType, Policy>& /* dist */)
145   { // Range of permissible values for random variable x.
146      using boost::math::tools::max_value;
147      return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + 'infinity'.
148      // Note RealType infinity is NOT permitted, only max_value.
149   }
150 
151   template <class RealType, class Policy>
support(const uniform_distribution<RealType,Policy> & dist)152   inline const std::pair<RealType, RealType> support(const uniform_distribution<RealType, Policy>& dist)
153   { // Range of supported values for random variable x.
154      // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
155      using boost::math::tools::max_value;
156      return std::pair<RealType, RealType>(dist.lower(),  dist.upper());
157   }
158 
159   template <class RealType, class Policy>
pdf(const uniform_distribution<RealType,Policy> & dist,const RealType & x)160   inline RealType pdf(const uniform_distribution<RealType, Policy>& dist, const RealType& x)
161   {
162     RealType lower = dist.lower();
163     RealType upper = dist.upper();
164     RealType result = 0; // of checks.
165     if(false == detail::check_uniform("boost::math::pdf(const uniform_distribution<%1%>&, %1%)", lower, upper, &result, Policy()))
166     {
167       return result;
168     }
169     if(false == detail::check_uniform_x("boost::math::pdf(const uniform_distribution<%1%>&, %1%)", x, &result, Policy()))
170     {
171       return result;
172     }
173 
174     if((x < lower) || (x > upper) )
175     {
176       return 0;
177     }
178     else
179     {
180       return 1 / (upper - lower);
181     }
182   } // RealType pdf(const uniform_distribution<RealType, Policy>& dist, const RealType& x)
183 
184   template <class RealType, class Policy>
cdf(const uniform_distribution<RealType,Policy> & dist,const RealType & x)185   inline RealType cdf(const uniform_distribution<RealType, Policy>& dist, const RealType& x)
186   {
187     RealType lower = dist.lower();
188     RealType upper = dist.upper();
189     RealType result = 0; // of checks.
190     if(false == detail::check_uniform("boost::math::cdf(const uniform_distribution<%1%>&, %1%)",lower, upper, &result, Policy()))
191     {
192       return result;
193     }
194     if(false == detail::check_uniform_x("boost::math::cdf(const uniform_distribution<%1%>&, %1%)", x, &result, Policy()))
195     {
196       return result;
197     }
198     if (x < lower)
199     {
200       return 0;
201     }
202     if (x > upper)
203     {
204       return 1;
205     }
206     return (x - lower) / (upper - lower); // lower <= x <= upper
207   } // RealType cdf(const uniform_distribution<RealType, Policy>& dist, const RealType& x)
208 
209   template <class RealType, class Policy>
quantile(const uniform_distribution<RealType,Policy> & dist,const RealType & p)210   inline RealType quantile(const uniform_distribution<RealType, Policy>& dist, const RealType& p)
211   {
212     RealType lower = dist.lower();
213     RealType upper = dist.upper();
214     RealType result = 0; // of checks
215     if(false == detail::check_uniform("boost::math::quantile(const uniform_distribution<%1%>&, %1%)",lower, upper, &result, Policy()))
216     {
217       return result;
218     }
219     if(false == detail::check_probability("boost::math::quantile(const uniform_distribution<%1%>&, %1%)", p, &result, Policy()))
220     {
221       return result;
222     }
223     if(p == 0)
224     {
225       return lower;
226     }
227     if(p == 1)
228     {
229       return upper;
230     }
231     return p * (upper - lower) + lower;
232   } // RealType quantile(const uniform_distribution<RealType, Policy>& dist, const RealType& p)
233 
234   template <class RealType, class Policy>
cdf(const complemented2_type<uniform_distribution<RealType,Policy>,RealType> & c)235   inline RealType cdf(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c)
236   {
237     RealType lower = c.dist.lower();
238     RealType upper = c.dist.upper();
239     RealType x = c.param;
240     RealType result = 0; // of checks.
241     if(false == detail::check_uniform("boost::math::cdf(const uniform_distribution<%1%>&, %1%)", lower, upper, &result, Policy()))
242     {
243       return result;
244     }
245     if(false == detail::check_uniform_x("boost::math::cdf(const uniform_distribution<%1%>&, %1%)", x, &result, Policy()))
246     {
247       return result;
248     }
249     if (x < lower)
250     {
251       return 1;
252     }
253     if (x > upper)
254     {
255       return 0;
256     }
257     return (upper - x) / (upper - lower);
258   } // RealType cdf(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c)
259 
260   template <class RealType, class Policy>
quantile(const complemented2_type<uniform_distribution<RealType,Policy>,RealType> & c)261   inline RealType quantile(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c)
262   {
263     RealType lower = c.dist.lower();
264     RealType upper = c.dist.upper();
265     RealType q = c.param;
266     RealType result = 0; // of checks.
267     if(false == detail::check_uniform("boost::math::quantile(const uniform_distribution<%1%>&, %1%)", lower, upper, &result, Policy()))
268     {
269       return result;
270     }
271     if(false == detail::check_probability("boost::math::quantile(const uniform_distribution<%1%>&, %1%)", q, &result, Policy()))
272     {
273        return result;
274     }
275     if(q == 0)
276     {
277        return upper;
278     }
279     if(q == 1)
280     {
281        return lower;
282     }
283     return -q * (upper - lower) + upper;
284   } // RealType quantile(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c)
285 
286   template <class RealType, class Policy>
mean(const uniform_distribution<RealType,Policy> & dist)287   inline RealType mean(const uniform_distribution<RealType, Policy>& dist)
288   {
289     RealType lower = dist.lower();
290     RealType upper = dist.upper();
291     RealType result = 0;  // of checks.
292     if(false == detail::check_uniform("boost::math::mean(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
293     {
294       return result;
295     }
296     return (lower + upper ) / 2;
297   } // RealType mean(const uniform_distribution<RealType, Policy>& dist)
298 
299   template <class RealType, class Policy>
variance(const uniform_distribution<RealType,Policy> & dist)300   inline RealType variance(const uniform_distribution<RealType, Policy>& dist)
301   {
302     RealType lower = dist.lower();
303     RealType upper = dist.upper();
304     RealType result = 0; // of checks.
305     if(false == detail::check_uniform("boost::math::variance(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
306     {
307       return result;
308     }
309     return (upper - lower) * ( upper - lower) / 12;
310     // for standard uniform = 0.833333333333333333333333333333333333333333;
311   } // RealType variance(const uniform_distribution<RealType, Policy>& dist)
312 
313   template <class RealType, class Policy>
mode(const uniform_distribution<RealType,Policy> & dist)314   inline RealType mode(const uniform_distribution<RealType, Policy>& dist)
315   {
316     RealType lower = dist.lower();
317     RealType upper = dist.upper();
318     RealType result = 0; // of checks.
319     if(false == detail::check_uniform("boost::math::mode(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
320     {
321       return result;
322     }
323     result = lower; // Any value [lower, upper] but arbitrarily choose lower.
324     return result;
325   }
326 
327   template <class RealType, class Policy>
median(const uniform_distribution<RealType,Policy> & dist)328   inline RealType median(const uniform_distribution<RealType, Policy>& dist)
329   {
330     RealType lower = dist.lower();
331     RealType upper = dist.upper();
332     RealType result = 0; // of checks.
333     if(false == detail::check_uniform("boost::math::median(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
334     {
335       return result;
336     }
337     return (lower + upper) / 2; //
338   }
339   template <class RealType, class Policy>
skewness(const uniform_distribution<RealType,Policy> & dist)340   inline RealType skewness(const uniform_distribution<RealType, Policy>& dist)
341   {
342     RealType lower = dist.lower();
343     RealType upper = dist.upper();
344     RealType result = 0; // of checks.
345     if(false == detail::check_uniform("boost::math::skewness(const uniform_distribution<%1%>&)",lower, upper, &result, Policy()))
346     {
347       return result;
348     }
349     return 0;
350   } // RealType skewness(const uniform_distribution<RealType, Policy>& dist)
351 
352   template <class RealType, class Policy>
kurtosis_excess(const uniform_distribution<RealType,Policy> & dist)353   inline RealType kurtosis_excess(const uniform_distribution<RealType, Policy>& dist)
354   {
355     RealType lower = dist.lower();
356     RealType upper = dist.upper();
357     RealType result = 0;  // of checks.
358     if(false == detail::check_uniform("boost::math::kurtosis_execess(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
359     {
360       return result;
361     }
362     return static_cast<RealType>(-6)/5; //  -6/5 = -1.2;
363   } // RealType kurtosis_excess(const uniform_distribution<RealType, Policy>& dist)
364 
365   template <class RealType, class Policy>
kurtosis(const uniform_distribution<RealType,Policy> & dist)366   inline RealType kurtosis(const uniform_distribution<RealType, Policy>& dist)
367   {
368     return kurtosis_excess(dist) + 3;
369   }
370 
371 } // namespace math
372 } // namespace boost
373 
374 // This include must be at the end, *after* the accessors
375 // for this distribution have been defined, in order to
376 // keep compilers that support two-phase lookup happy.
377 #include <boost/math/distributions/detail/derived_accessors.hpp>
378 
379 #endif // BOOST_STATS_UNIFORM_HPP
380 
381 
382 
383