Ticket #1054: parameter_test.cpp

File parameter_test.cpp, 9.1 KB (added by John Maddock, 15 years ago)

test case.

Line 
1
2#define BOOST_PARAMETER_MAX_ARITY 15
3
4#include <boost/parameter.hpp>
5#include <boost/mpl/list.hpp>
6#include <boost/mpl/contains.hpp>
7
8//
9// Define macros for our default policies, if they're not defined already:
10//
11#ifndef BOOST_MATH_DOMAIN_ERROR_POLICY
12#define BOOST_MATH_DOMAIN_ERROR_POLICY throw_on_error
13#endif
14#ifndef BOOST_MATH_POLE_ERROR_POLICY
15#define BOOST_MATH_POLE_ERROR_POLICY throw_on_error
16#endif
17#ifndef BOOST_MATH_OVERFLOW_ERROR_POLICY
18#define BOOST_MATH_OVERFLOW_ERROR_POLICY throw_on_error
19#endif
20#ifndef BOOST_MATH_EVALUATION_ERROR_POLICY
21#define BOOST_MATH_EVALUATION_ERROR_POLICY throw_on_error
22#endif
23#ifndef BOOST_MATH_UNDERFLOW_ERROR_POLICY
24#define BOOST_MATH_UNDERFLOW_ERROR_POLICY ignor_error
25#endif
26#ifndef BOOST_MATH_DENORM_ERROR_POLICY
27#define BOOST_MATH_DENORM_ERROR_POLICY ignor_error
28#endif
29#ifndef BOOST_MATH_DIGITS10_POLICY
30#define BOOST_MATH_DIGITS10_POLICY -1
31#endif
32#ifndef BOOST_MATH_PROMOTE_FLOAT_POLICY
33#define BOOST_MATH_PROMOTE_FLOAT_POLICY true
34#endif
35#ifndef BOOST_MATH_PROMOTE_DOUBLE_POLICY
36#define BOOST_MATH_PROMOTE_DOUBLE_POLICY true
37#endif
38#ifndef BOOST_MATH_DISCRETE_QUANTILE_POLICY
39#define BOOST_MATH_DISCRETE_QUANTILE_POLICY integer_outside
40#endif
41
42struct any_convertable
43{
44 template <class T>
45 any_convertable(const T&);
46};
47
48
49#define BOOST_MATH_META_INT(type, name)\
50 template <type N> struct name : public boost::mpl::int_<N>{};\
51 namespace detail{\
52 template <class T> struct is_##name##_imp\
53 {\
54 template <type N> static char test(const name<N>&);\
55 static double test(any_convertable);\
56 BOOST_STATIC_CONSTANT(bool, value = sizeof(test(T())) == 1);\
57 };\
58 }\
59 template <class T> struct is_##name : public boost::mpl::bool_< ::detail::is_##name##_imp<T>::value>{};
60
61#define BOOST_MATH_META_BOOL(name)\
62 template <bool N> struct name : public boost::mpl::bool_<N>{};\
63 namespace detail{\
64 template <class T> struct is_##name##_imp\
65 {\
66 template <bool N> static char test(const name<N>&);\
67 static double test(any_convertable);\
68 BOOST_STATIC_CONSTANT(bool, value = sizeof(test(T())) == 1);\
69 };\
70 }\
71 template <class T> struct is_##name : public boost::mpl::bool_< ::detail::is_##name##_imp<T>::value>{};
72
73//
74// Begin by defining policy types for error handling:
75//
76enum error_policy_type
77{
78 throw_on_error = 0,
79 errno_on_error = 1,
80 ignor_error = 2,
81 user_error = 3
82};
83
84BOOST_MATH_META_INT(error_policy_type, domain_error)
85BOOST_MATH_META_INT(error_policy_type, pole_error)
86BOOST_MATH_META_INT(error_policy_type, overflow_error)
87BOOST_MATH_META_INT(error_policy_type, underflow_error)
88BOOST_MATH_META_INT(error_policy_type, denorm_error)
89BOOST_MATH_META_INT(error_policy_type, evaluation_error)
90
91//
92// Policy types for internal promotion:
93//
94BOOST_MATH_META_BOOL(promote_float);
95BOOST_MATH_META_BOOL(promote_double);
96//
97// Policy types for discrete quantiles:
98//
99enum discrete_quantile_policy_type
100{
101 real,
102 integer_outside,
103 integer_inside,
104 integer_below,
105 integer_above
106};
107
108BOOST_MATH_META_INT(discrete_quantile_policy_type, discrete_quantile);
109//
110// Precision:
111//
112BOOST_MATH_META_INT(int, digits10);
113BOOST_MATH_META_INT(int, digits2);
114//
115// Define the names for each possible policy:
116//
117#define BOOST_MATH_PARAMETER(name)\
118 BOOST_PARAMETER_TEMPLATE_KEYWORD(name##_name)\
119 BOOST_PARAMETER_NAME(name##_name)
120//
121// Error handlers:
122//
123BOOST_MATH_PARAMETER(domain_error)
124BOOST_MATH_PARAMETER(pole_error)
125BOOST_MATH_PARAMETER(overflow_error)
126BOOST_MATH_PARAMETER(underflow_error)
127BOOST_MATH_PARAMETER(denorm_error)
128BOOST_MATH_PARAMETER(evaluation_error)
129//
130// Precision:
131//
132BOOST_MATH_PARAMETER(digits10)
133BOOST_MATH_PARAMETER(digits2)
134//
135// Internal promotion:
136//
137BOOST_MATH_PARAMETER(promote_float)
138BOOST_MATH_PARAMETER(promote_double)
139//
140// Discrete quantile handling:
141//
142BOOST_MATH_PARAMETER(discrete_quantile)
143
144namespace detail{
145//
146// Trait to work out bits precision from digits10 and digits2:
147//
148template <class Digits10, class Digits2>
149struct precision
150{
151 //
152 // Now work out the precision:
153 //
154 typedef digits2<((Digits10::value + 1) * 1000L) / 301L> digits2_type;
155public:
156#ifdef __BORLANDC__
157 typedef typename boost::mpl::if_c<
158 (Digits2::value > ::detail::precision<Digits10,Digits2>::digits2_type::value),
159 Digits2, digits2_type>::type type;
160#else
161 typedef typename boost::mpl::if_c<
162 (Digits2::value > digits2_type::value),
163 Digits2, digits2_type>::type type;
164#endif
165};
166
167}
168
169//
170// Define template signature complete with error checking of types:
171//
172using boost::mpl::_;
173typedef boost::parameter::parameters<
174 boost::parameter::optional<boost::parameter::deduced<tag::domain_error_name>, is_domain_error<boost::mpl::_> >
175 , boost::parameter::optional<boost::parameter::deduced<tag::pole_error_name>, is_pole_error<boost::mpl::_> >
176 , boost::parameter::optional<boost::parameter::deduced<tag::overflow_error_name>, is_overflow_error<boost::mpl::_> >
177 , boost::parameter::optional<boost::parameter::deduced<tag::underflow_error_name>, is_underflow_error<boost::mpl::_> >
178 , boost::parameter::optional<boost::parameter::deduced<tag::denorm_error_name>, is_denorm_error<boost::mpl::_> >
179 , boost::parameter::optional<boost::parameter::deduced<tag::evaluation_error_name>, is_evaluation_error<boost::mpl::_> >
180 , boost::parameter::optional<boost::parameter::deduced<tag::digits10_name>, is_digits10<boost::mpl::_> >
181 , boost::parameter::optional<boost::parameter::deduced<tag::digits2_name>, is_digits2<boost::mpl::_> >
182 , boost::parameter::optional<boost::parameter::deduced<tag::promote_float_name>, is_promote_float<boost::mpl::_> >
183 , boost::parameter::optional<boost::parameter::deduced<tag::promote_double_name>, is_promote_double<boost::mpl::_> >
184 , boost::parameter::optional<boost::parameter::deduced<tag::discrete_quantile_name>, is_discrete_quantile<boost::mpl::_> >
185> policy_signature;
186
187//
188// Now define the policy type with enough arguments to handle all
189// the policies:
190//
191template <class A1 = boost::parameter::void_,
192 class A2 = boost::parameter::void_,
193 class A3 = boost::parameter::void_,
194 class A4 = boost::parameter::void_,
195 class A5 = boost::parameter::void_,
196 class A6 = boost::parameter::void_,
197 class A7 = boost::parameter::void_,
198 class A8 = boost::parameter::void_,
199 class A9 = boost::parameter::void_,
200 class A10 = boost::parameter::void_,
201 class A11 = boost::parameter::void_>
202struct policy
203{
204 typedef policy_signature::bind<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_> bound_type;
205 typedef typename bound_type::type args;
206
207 // This next line is the one that causes the problem:
208 typedef typename boost::parameter::binding<
209 args, tag::domain_error_name, domain_error<BOOST_MATH_DOMAIN_ERROR_POLICY> >::type domain_error_type;
210 typedef typename boost::parameter::binding<
211 args, tag::pole_error_name, pole_error<BOOST_MATH_POLE_ERROR_POLICY> >::type pole_error_type;
212 typedef typename boost::parameter::binding<
213 args, tag::overflow_error_name, overflow_error<BOOST_MATH_OVERFLOW_ERROR_POLICY> >::type overflow_error_type;
214 typedef typename boost::parameter::binding<
215 args, tag::underflow_error_name, underflow_error<BOOST_MATH_UNDERFLOW_ERROR_POLICY> >::type underflow_error_type;
216 typedef typename boost::parameter::binding<
217 args, tag::denorm_error_name, denorm_error<BOOST_MATH_DENORM_ERROR_POLICY> >::type denorm_error_type;
218 typedef typename boost::parameter::binding<
219 args, tag::evaluation_error_name, evaluation_error<BOOST_MATH_EVALUATION_ERROR_POLICY> >::type evaluation_error_type;
220private:
221 //
222 // Now work out the precision:
223 //
224 typedef typename boost::parameter::binding<
225 args, tag::digits10_name, digits10<BOOST_MATH_DIGITS10_POLICY> >::type digits10_type;
226 typedef typename boost::parameter::binding<
227 args, tag::digits2_name, digits2<-1> >::type bits_precision_type;
228public:
229 typedef typename detail::precision<digits10_type, bits_precision_type>::type precision_type;
230 //
231 // Internal promotion:
232 //
233 typedef typename boost::parameter::binding<
234 args, tag::promote_float_name, boost::mpl::bool_<BOOST_MATH_PROMOTE_FLOAT_POLICY> >::type float_promote_type;
235 typedef typename boost::parameter::binding<
236 args, tag::promote_double_name, boost::mpl::bool_<BOOST_MATH_PROMOTE_DOUBLE_POLICY> >::type double_promote_type;
237 //
238 // Discrete quantiles:
239 //
240 typedef typename boost::parameter::binding<
241 args, tag::discrete_quantile_name, discrete_quantile<BOOST_MATH_DISCRETE_QUANTILE_POLICY> >::type discrete_quantile_type;
242};
243
244// Instantiate a policy object:
245policy<
246 domain_error<throw_on_error>,
247 pole_error<throw_on_error>,
248 overflow_error<throw_on_error>,
249 underflow_error<throw_on_error>,
250 denorm_error<throw_on_error>,
251 evaluation_error<throw_on_error> > throw_policy;
252
253