mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-04 05:50:31 -05:00 
			
		
		
		
	
		
			
	
	
		
			512 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			512 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:pol_tutorial Policy Tutorial]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:what_is_a_policy So Just What is a Policy Anyway?]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								A policy is a compile-time mechanism for customising the behaviour of a
							 | 
						||
| 
								 | 
							
								special function, or a statistical distribution.  With Policies you can
							 | 
						||
| 
								 | 
							
								control:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* What action to take when an error occurs.
							 | 
						||
| 
								 | 
							
								* What happens when you call a function that is mathematically undefined
							 | 
						||
| 
								 | 
							
								(for example, if you ask for the mean of a Cauchy distribution).
							 | 
						||
| 
								 | 
							
								* What happens when you ask for a quantile of a discrete distribution.
							 | 
						||
| 
								 | 
							
								* Whether the library is allowed to internally promote `float` to `double`
							 | 
						||
| 
								 | 
							
								and `double` to `long double` in order to improve precision.
							 | 
						||
| 
								 | 
							
								* What precision to use when calculating the result.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Some of these policies could arguably be runtime variables, but then we couldn't
							 | 
						||
| 
								 | 
							
								use compile-time dispatch internally to select the best evaluation method
							 | 
						||
| 
								 | 
							
								for the given policies.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For this reason a Policy is a /type/: in fact it's an instance of the
							 | 
						||
| 
								 | 
							
								class template `boost::math::policies::policy<>`.  This class is just a
							 | 
						||
| 
								 | 
							
								compile-time-container of user-selected policies (sometimes called a type-list):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   using namespace boost::math::policies;
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   // Define a policy that sets ::errno on overflow, and does
							 | 
						||
| 
								 | 
							
								   // not promote double to long double internally:
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   typedef policy<domain_error<errno_on_error>, promote_double<false> > mypolicy;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect] [/section:what_is_a_policy So Just What is a Policy Anyway?]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:policy_tut_defaults Policies Have Sensible Defaults]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Most of the time you can just ignore the policy framework.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								['*The defaults for the various policies are as follows,
							 | 
						||
| 
								 | 
							
								if these work OK for you then you can stop reading now!]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[variablelist
							 | 
						||
| 
								 | 
							
								[[Domain Error][Throws a `std::domain_error` exception.]]
							 | 
						||
| 
								 | 
							
								[[Pole Error][Occurs when a function is evaluated at a pole: throws a `std::domain_error` exception.]]
							 | 
						||
| 
								 | 
							
								[[Overflow Error][Throws a `std::overflow_error` exception.]]
							 | 
						||
| 
								 | 
							
								[[Underflow][Ignores the underflow, and returns zero.]]
							 | 
						||
| 
								 | 
							
								[[Denormalised Result][Ignores the fact that the result is denormalised, and returns it.]]
							 | 
						||
| 
								 | 
							
								[[Rounding Error][Throws a `boost::math::rounding_error` exception.]]
							 | 
						||
| 
								 | 
							
								[[Internal Evaluation Error][Throws a `boost::math::evaluation_error` exception.]]
							 | 
						||
| 
								 | 
							
								[[Indeterminate Result Error][Returns a result that depends on the function where the error occurred.]]
							 | 
						||
| 
								 | 
							
								[[Promotion of float to double][Does occur by default - gives full float precision results.]]
							 | 
						||
| 
								 | 
							
								[[Promotion of double to long double][Does occur by default if long double offers
							 | 
						||
| 
								 | 
							
								   more precision than double.]]
							 | 
						||
| 
								 | 
							
								[[Precision of Approximation Used][By default uses an approximation that
							 | 
						||
| 
								 | 
							
								   will result in the lowest level of error for the type of the result.]]
							 | 
						||
| 
								 | 
							
								[[Behaviour of Discrete Quantiles]
							 | 
						||
| 
								 | 
							
								   [
							 | 
						||
| 
								 | 
							
								   The quantile function will by default return an integer result that has been
							 | 
						||
| 
								 | 
							
								   /rounded outwards/.  That is to say lower quantiles (where the probability is
							 | 
						||
| 
								 | 
							
								   less than 0.5) are rounded downward, and upper quantiles (where the probability
							 | 
						||
| 
								 | 
							
								   is greater than 0.5) are rounded upwards.  This behaviour
							 | 
						||
| 
								 | 
							
								   ensures that if an X% quantile is requested, then /at least/ the requested
							 | 
						||
| 
								 | 
							
								   coverage will be present in the central region, and /no more than/
							 | 
						||
| 
								 | 
							
								   the requested coverage will be present in the tails.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This behaviour can be changed so that the quantile functions are rounded
							 | 
						||
| 
								 | 
							
								   differently, or even return a real-valued result using
							 | 
						||
| 
								 | 
							
								   [link math_toolkit.pol_overview Policies].  It is strongly
							 | 
						||
| 
								 | 
							
								   recommended that you read the tutorial
							 | 
						||
| 
								 | 
							
								   [link math_toolkit.pol_tutorial.understand_dis_quant
							 | 
						||
| 
								 | 
							
								   Understanding Quantiles of Discrete Distributions] before
							 | 
						||
| 
								 | 
							
								   using the quantile function on a discrete distribution.  The
							 | 
						||
| 
								 | 
							
								   [link math_toolkit.pol_ref.discrete_quant_ref reference docs]
							 | 
						||
| 
								 | 
							
								   describe how to change the rounding policy
							 | 
						||
| 
								 | 
							
								   for these distributions.
							 | 
						||
| 
								 | 
							
								]]
							 | 
						||
| 
								 | 
							
								]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								What's more, if you define your own policy type, then it automatically
							 | 
						||
| 
								 | 
							
								inherits the defaults for any policies not explicitly set, so given:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   using namespace boost::math::policies;
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   // Define a policy that sets ::errno on overflow, and does
							 | 
						||
| 
								 | 
							
								   // not promote double to long double internally:
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   typedef policy<domain_error<errno_on_error>, promote_double<false> > mypolicy;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								then `mypolicy` defines a policy where only the overflow error handling and
							 | 
						||
| 
								 | 
							
								`double`-promotion policies differ from the defaults.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect][/section:policy_tut_defaults Policies Have Sensible Defaults]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:policy_usage So How are Policies Used Anyway?]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The details follow later, but basically policies can be set by either:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* Defining some macros that change the default behaviour: [*this is the
							 | 
						||
| 
								 | 
							
								   recommended method for setting installation-wide policies].
							 | 
						||
| 
								 | 
							
								* By instantiating a distribution object with an explicit policy:
							 | 
						||
| 
								 | 
							
								   this is mainly reserved for ad hoc policy changes.
							 | 
						||
| 
								 | 
							
								* By passing a policy to a special function as an optional final argument:
							 | 
						||
| 
								 | 
							
								   this is mainly reserved for ad hoc policy changes.
							 | 
						||
| 
								 | 
							
								* By using some helper macros to define a set of functions or distributions
							 | 
						||
| 
								 | 
							
								in the current namespace that use a specific policy: [*this is the
							 | 
						||
| 
								 | 
							
								recommended method for setting policies on a project- or translation-unit-wide
							 | 
						||
| 
								 | 
							
								basis].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The following sections introduce these methods in more detail.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect] [/section:policy_usage So How are Policies Used Anyway?]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:changing_policy_defaults Changing the Policy Defaults]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The default policies used by the library are changed by the usual
							 | 
						||
| 
								 | 
							
								configuration macro method.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For example, passing `-DBOOST_MATH_DOMAIN_ERROR_POLICY=errno_on_error` to
							 | 
						||
| 
								 | 
							
								your compiler will cause domain errors to set `::errno` and return a __NaN
							 | 
						||
| 
								 | 
							
								rather than the usual default behaviour of throwing a `std::domain_error`
							 | 
						||
| 
								 | 
							
								exception.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[tip For Microsoft Visual Studio,you can add to the Project Property Page,
							 | 
						||
| 
								 | 
							
								C/C++, Preprocessor, Preprocessor definitions like:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								``BOOST_MATH_ASSERT_UNDEFINED_POLICY=0
							 | 
						||
| 
								 | 
							
								BOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error``
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This may be helpful to avoid complications with pre-compiled headers
							 | 
						||
| 
								 | 
							
								that may mean that the equivalent definitions in source code:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								``#define BOOST_MATH_ASSERT_UNDEFINED_POLICY false
							 | 
						||
| 
								 | 
							
								#define BOOST_MATH_OVERFLOW_ERROR_POLICY errno_on_error``
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*may be ignored*.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The compiler command line shows:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								``/D "BOOST_MATH_ASSERT_UNDEFINED_POLICY=0"
							 | 
						||
| 
								 | 
							
								/D "BOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error"``
							 | 
						||
| 
								 | 
							
								] [/MSVC tip]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								There is however a very important caveat to this:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[important
							 | 
						||
| 
								 | 
							
								[*['Default policies changed by setting configuration macros must be changed
							 | 
						||
| 
								 | 
							
								uniformly in every translation unit in the program.]]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Failure to follow this rule may result in violations of the "One
							 | 
						||
| 
								 | 
							
								Definition Rule (ODR)" and result in unpredictable program behaviour.]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								That means there are only two safe ways to use these macros:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* Edit them in [@../../../../boost/math/tools/user.hpp boost/math/tools/user.hpp],
							 | 
						||
| 
								 | 
							
								so that the defaults are set on an installation-wide basis.
							 | 
						||
| 
								 | 
							
								Unfortunately this may not be convenient if
							 | 
						||
| 
								 | 
							
								you are using a pre-installed Boost distribution (on Linux for example).
							 | 
						||
| 
								 | 
							
								* Set the defines in your project's Makefile or build environment, so that they
							 | 
						||
| 
								 | 
							
								are set uniformly across all translation units.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								What you should *not* do is:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* Set the defines in the source file using `#define` as doing so
							 | 
						||
| 
								 | 
							
								almost certainly will break your program, unless you're absolutely
							 | 
						||
| 
								 | 
							
								certain that the program is restricted to a single translation unit.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								And, yes, you will find examples in our test programs where we break this
							 | 
						||
| 
								 | 
							
								rule: but only because we know there will always be a single
							 | 
						||
| 
								 | 
							
								translation unit only: ['don't say that you weren't warned!]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[import ../../example/error_handling_example.cpp]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[error_handling_example]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect] [/section:changing_policy_defaults Changing the Policy Defaults]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:ad_hoc_dist_policies Setting Policies for Distributions on an Ad Hoc Basis]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								All of the statistical distributions in this library are class templates
							 | 
						||
| 
								 | 
							
								that accept two template parameters:
							 | 
						||
| 
								 | 
							
								real type (float, double ...) and policy (how to handle exceptional events),
							 | 
						||
| 
								 | 
							
								both with sensible defaults, for example:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   namespace boost{ namespace math{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   template <class RealType = double, class Policy = policies::policy<> >
							 | 
						||
| 
								 | 
							
								   class fisher_f_distribution;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   typedef fisher_f_distribution<> fisher_f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   }}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This policy gets used by all the accessor functions that accept
							 | 
						||
| 
								 | 
							
								a distribution as an argument, and forwarded to all the functions called
							 | 
						||
| 
								 | 
							
								by these.  So if you use the shorthand-typedef for the distribution, then you get
							 | 
						||
| 
								 | 
							
								`double` precision arithmetic and all the default policies.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								However, say for example we wanted to evaluate the quantile
							 | 
						||
| 
								 | 
							
								of the binomial distribution at float precision, without internal
							 | 
						||
| 
								 | 
							
								promotion to double, and with the result rounded to the /nearest/
							 | 
						||
| 
								 | 
							
								integer, then here's how it can be done:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[import ../../example/policy_eg_3.cpp]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[policy_eg_3]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Which outputs:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[pre quantile is: 40]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect][/section:ad_hoc_dist_policies Setting Policies for Distributions on an Ad Hoc Basis]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:ad_hoc_sf_policies Changing the Policy on an Ad Hoc Basis for the Special Functions]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								All of the special functions in this library come in two overloaded forms,
							 | 
						||
| 
								 | 
							
								one with a final "policy" parameter, and one without.  For example:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   namespace boost{ namespace math{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   template <class RealType, class Policy>
							 | 
						||
| 
								 | 
							
								   RealType tgamma(RealType, const Policy&);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   template <class RealType>
							 | 
						||
| 
								 | 
							
								   RealType tgamma(RealType);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   }} // namespaces
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Normally, the second version is just a forwarding wrapper to the first
							 | 
						||
| 
								 | 
							
								like this:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   template <class RealType>
							 | 
						||
| 
								 | 
							
								   inline RealType tgamma(RealType x)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      return tgamma(x, policies::policy<>());
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								So calling a special function with a specific policy
							 | 
						||
| 
								 | 
							
								is just a matter of defining the policy type to use
							 | 
						||
| 
								 | 
							
								and passing it as the final parameter.  For example,
							 | 
						||
| 
								 | 
							
								suppose we want `tgamma` to behave in a C-compatible
							 | 
						||
| 
								 | 
							
								fashion and set `::errno` when an error occurs, and never
							 | 
						||
| 
								 | 
							
								throw an exception:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[import ../../example/policy_eg_1.cpp]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[policy_eg_1]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								which outputs:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[pre
							 | 
						||
| 
								 | 
							
								Result of tgamma(30000) is: 1.#INF
							 | 
						||
| 
								 | 
							
								errno = 34
							 | 
						||
| 
								 | 
							
								Result of tgamma(-10) is: 1.#QNAN
							 | 
						||
| 
								 | 
							
								errno = 33
							 | 
						||
| 
								 | 
							
								]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Alternatively, for ad hoc use, we can use the `make_policy`
							 | 
						||
| 
								 | 
							
								helper function to create a policy for us: this usage is more
							 | 
						||
| 
								 | 
							
								verbose, so is probably only preferred when a policy is going
							 | 
						||
| 
								 | 
							
								to be used once only:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[import ../../example/policy_eg_2.cpp]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[policy_eg_2]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect] [/section:ad_hoc_sf_policies Changing the Policy on an Ad Hoc Basis for the Special Functions]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:namespace_policies Setting Policies at Namespace or Translation Unit Scope]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Sometimes what you want to do is just change a set of policies within
							 | 
						||
| 
								 | 
							
								the current scope: *the one thing you should not do in this situation
							 | 
						||
| 
								 | 
							
								is use the configuration macros*, as this can lead to "One Definition
							 | 
						||
| 
								 | 
							
								Rule" violations.  Instead this library provides a pair of macros
							 | 
						||
| 
								 | 
							
								especially for this purpose.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Let's consider the special functions first: we can declare a set of
							 | 
						||
| 
								 | 
							
								forwarding functions that all use a specific policy using the
							 | 
						||
| 
								 | 
							
								macro BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(['Policy]).  This
							 | 
						||
| 
								 | 
							
								macro should be used either inside a unique namespace set aside for the
							 | 
						||
| 
								 | 
							
								purpose (for example, a C namespace for a C-style policy),
							 | 
						||
| 
								 | 
							
								or an unnamed namespace if you just want the functions
							 | 
						||
| 
								 | 
							
								visible in global scope for the current file only.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[import ../../example/policy_eg_4.cpp]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[policy_eg_4]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The same mechanism works well at file scope as well, by using an unnamed
							 | 
						||
| 
								 | 
							
								namespace, we can ensure that these declarations don't conflict with any
							 | 
						||
| 
								 | 
							
								alternate policies present in other translation units:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[import ../../example/policy_eg_5.cpp]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[policy_eg_5]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Handling policies for the statistical distributions is very similar except that now
							 | 
						||
| 
								 | 
							
								the macro BOOST_MATH_DECLARE_DISTRIBUTIONS accepts two parameters: the
							 | 
						||
| 
								 | 
							
								floating point type to use, and the policy type to apply.  For example:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_DECLARE_DISTRIBUTIONS(double, mypolicy)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Results a set of typedefs being defined like this:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   typedef boost::math::normal_distribution<double, mypolicy> normal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The name of each typedef is the same as the name of the distribution
							 | 
						||
| 
								 | 
							
								class template, but without the "_distribution" suffix.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[import ../../example/policy_eg_6.cpp]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[policy_eg_6]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[note
							 | 
						||
| 
								 | 
							
								There is an important limitation to note: you can *not use the macros
							 | 
						||
| 
								 | 
							
								BOOST_MATH_DECLARE_DISTRIBUTIONS and BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS
							 | 
						||
| 
								 | 
							
								['in the same namespace]*,  as doing so creates ambiguities between functions
							 | 
						||
| 
								 | 
							
								and distributions of the same name.
							 | 
						||
| 
								 | 
							
								]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								As before, the same mechanism works well at file scope as well: by using an unnamed
							 | 
						||
| 
								 | 
							
								namespace, we can ensure that these declarations don't conflict with any
							 | 
						||
| 
								 | 
							
								alternate policies present in other translation units:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[import ../../example/policy_eg_7.cpp]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[policy_eg_7]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect][/section:namespace_policies Setting Policies at Namespace or Translation Unit Scope]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:user_def_err_pol Calling User Defined Error Handlers]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[import ../../example/policy_eg_8.cpp]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[policy_eg_8]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[import ../../example/policy_eg_9.cpp]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[policy_eg_9]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect] [/section:user_def_err_pol Calling User Defined Error Handlers]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:understand_dis_quant Understanding Quantiles of Discrete Distributions]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Discrete distributions present us with a problem when calculating the
							 | 
						||
| 
								 | 
							
								quantile: we are starting from a continuous real-valued variable - the
							 | 
						||
| 
								 | 
							
								probability - but the result (the value of the random variable)
							 | 
						||
| 
								 | 
							
								should really be discrete.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Consider for example a Binomial distribution, with a sample size of
							 | 
						||
| 
								 | 
							
								50, and a success fraction of 0.5.  There are a variety of ways
							 | 
						||
| 
								 | 
							
								we can plot a discrete distribution, but if we plot the PDF
							 | 
						||
| 
								 | 
							
								as a step-function then it looks something like this:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[$../graphs/binomial_pdf.png]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Now lets suppose that the user asks for a the quantile that corresponds
							 | 
						||
| 
								 | 
							
								to a probability of 0.05, if we zoom in on the CDF for that region here's
							 | 
						||
| 
								 | 
							
								what we see:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[$../graphs/binomial_quantile_1.png]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								As can be seen there is no random variable that corresponds to
							 | 
						||
| 
								 | 
							
								a probability of exactly 0.05, so we're left with two choices as
							 | 
						||
| 
								 | 
							
								shown in the figure:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* We could round the result down to 18.
							 | 
						||
| 
								 | 
							
								* We could round the result up to 19.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In fact there's actually a third choice as well: we could "pretend" that the
							 | 
						||
| 
								 | 
							
								distribution was continuous and return a real valued result: in this case we
							 | 
						||
| 
								 | 
							
								would calculate a result of approximately 18.701 (this accurately
							 | 
						||
| 
								 | 
							
								reflects the fact that the result is nearer to 19 than 18).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								By using policies we can offer any of the above as options, but that
							 | 
						||
| 
								 | 
							
								still leaves the question: ['What is actually the right thing to do?]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								And in particular: ['What policy should we use by default?]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In coming to an answer we should realise that:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* Calculating an integer result is often much faster than
							 | 
						||
| 
								 | 
							
								calculating a real-valued result: in fact in our tests it
							 | 
						||
| 
								 | 
							
								was up to 20 times faster.
							 | 
						||
| 
								 | 
							
								* Normally people calculate quantiles so that they can perform
							 | 
						||
| 
								 | 
							
								a test of some kind: ['"If the random variable is less than N
							 | 
						||
| 
								 | 
							
								then we can reject our null-hypothesis with 90% confidence."]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								So there is a genuine benefit to calculating an integer result
							 | 
						||
| 
								 | 
							
								as well as it being "the right thing to do" from a philosophical
							 | 
						||
| 
								 | 
							
								point of view.  What's more if someone asks for a quantile at 0.05,
							 | 
						||
| 
								 | 
							
								then we can normally assume that they are asking for
							 | 
						||
| 
								 | 
							
								['[*at least] 95% of the probability to the right of the value chosen,
							 | 
						||
| 
								 | 
							
								and [*no more than] 5% of the probability to the left of the value chosen.]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In the above binomial example we would therefore round the result down to 18.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The converse applies to upper-quantiles: If the probability is greater than
							 | 
						||
| 
								 | 
							
								0.5 we would want to round the quantile up, ['so that [*at least] the requested
							 | 
						||
| 
								 | 
							
								probability is to the left of the value returned, and [*no more than] 1 - the
							 | 
						||
| 
								 | 
							
								requested probability is to the right of the value returned.]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Likewise for two-sided intervals, we would round lower quantiles down,
							 | 
						||
| 
								 | 
							
								and upper quantiles up.  This ensures that we have ['at least the requested
							 | 
						||
| 
								 | 
							
								probability in the central region] and ['no more than 1 minus the requested
							 | 
						||
| 
								 | 
							
								probability in the tail areas.]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For example, taking our 50 sample binomial distribution with a success fraction
							 | 
						||
| 
								 | 
							
								of 0.5, if we wanted a two sided 90% confidence interval, then we would ask
							 | 
						||
| 
								 | 
							
								for the 0.05 and 0.95 quantiles with the results ['rounded outwards] so that
							 | 
						||
| 
								 | 
							
								['at least 90% of the probability] is in the central area:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[$../graphs/binomial_pdf_3.png]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								So far so good, but there is in fact a trap waiting for the unwary here:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   quantile(binomial(50, 0.5), 0.05);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								returns 18 as the result, which is what we would expect from the graph above,
							 | 
						||
| 
								 | 
							
								and indeed there is no x greater than 18 for which:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   cdf(binomial(50, 0.5), x) <= 0.05;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								However:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   quantile(binomial(50, 0.5), 0.95);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								returns 31, and indeed while there is no x less than 31 for which:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   cdf(binomial(50, 0.5), x) >= 0.95;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								We might naively expect that for this symmetrical distribution the result
							 | 
						||
| 
								 | 
							
								would be 32 (since 32 = 50 - 18), but we need to remember that the cdf of
							 | 
						||
| 
								 | 
							
								the binomial is /inclusive/ of the random variable.  So while the left tail
							 | 
						||
| 
								 | 
							
								area /includes/ the quantile returned, the right tail area always excludes
							 | 
						||
| 
								 | 
							
								an upper quantile value: since that "belongs" to the central area.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Look at the graph above to see what's going on here: the lower quantile
							 | 
						||
| 
								 | 
							
								of 18 belongs to the left tail, so any value <= 18 is in the left tail.
							 | 
						||
| 
								 | 
							
								The upper quantile of 31 on the other hand belongs to the central area,
							 | 
						||
| 
								 | 
							
								so the tail area actually starts at 32, so any value > 31 is in the
							 | 
						||
| 
								 | 
							
								right tail.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Therefore if U and L are the upper and lower quantiles respectively, then
							 | 
						||
| 
								 | 
							
								a random variable X is in the tail area - where we would reject the null
							 | 
						||
| 
								 | 
							
								hypothesis if:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   X <= L || X > U
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								And the a variable X is inside the central region if:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   L < X <= U
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The moral here is to ['always be very careful with your comparisons
							 | 
						||
| 
								 | 
							
								when dealing with a discrete distribution], and if in doubt,
							 | 
						||
| 
								 | 
							
								['base your comparisons on CDF's instead].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[heading Other Rounding Policies are Available]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								As you would expect from a section on policies, you won't be surprised
							 | 
						||
| 
								 | 
							
								to know that other rounding options are available:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[variablelist
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[[integer_round_outwards]
							 | 
						||
| 
								 | 
							
								   [This is the default policy as described above: lower quantiles
							 | 
						||
| 
								 | 
							
								   are rounded down (probability < 0.5), and upper quantiles
							 | 
						||
| 
								 | 
							
								   (probability > 0.5) are rounded up.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   This gives /no more than/ the requested probability
							 | 
						||
| 
								 | 
							
								   in the tails, and /at least/ the requested probability
							 | 
						||
| 
								 | 
							
								   in the central area.]]
							 | 
						||
| 
								 | 
							
								[[integer_round_inwards]
							 | 
						||
| 
								 | 
							
								   [This is the exact opposite of the default policy:
							 | 
						||
| 
								 | 
							
								   lower quantiles
							 | 
						||
| 
								 | 
							
								   are rounded up (probability < 0.5),
							 | 
						||
| 
								 | 
							
								   and upper quantiles (probability > 0.5) are rounded down.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   This gives /at least/ the requested probability
							 | 
						||
| 
								 | 
							
								   in the tails, and /no more than/ the requested probability
							 | 
						||
| 
								 | 
							
								   in the central area.]]
							 | 
						||
| 
								 | 
							
								[[integer_round_down][This policy will always round the result down
							 | 
						||
| 
								 | 
							
								   no matter whether it is an upper or lower quantile]]
							 | 
						||
| 
								 | 
							
								[[integer_round_up][This policy will always round the result up
							 | 
						||
| 
								 | 
							
								   no matter whether it is an upper or lower quantile]]
							 | 
						||
| 
								 | 
							
								[[integer_round_nearest][This policy will always round the result
							 | 
						||
| 
								 | 
							
								   to the nearest integer
							 | 
						||
| 
								 | 
							
								   no matter whether it is an upper or lower quantile]]
							 | 
						||
| 
								 | 
							
								[[real][This policy will return a real valued result
							 | 
						||
| 
								 | 
							
								   for the quantile of a discrete distribution: this is
							 | 
						||
| 
								 | 
							
								   generally much slower than finding an integer result
							 | 
						||
| 
								 | 
							
								   but does allow for more sophisticated rounding policies.]]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[import ../../example/policy_eg_10.cpp]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[policy_eg_10]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect] [/section:pol_Tutorial Policy Tutorial]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[/ math.qbk
							 | 
						||
| 
								 | 
							
								  Copyright 2007, 2013 John Maddock and Paul A. Bristow.
							 | 
						||
| 
								 | 
							
								  Distributed under the Boost Software License, Version 1.0.
							 | 
						||
| 
								 | 
							
								  (See accompanying file LICENSE_1_0.txt or copy at
							 | 
						||
| 
								 | 
							
								  http://www.boost.org/LICENSE_1_0.txt).
							 | 
						||
| 
								 | 
							
								]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 |