]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/numeric/conversion/doc/requirements.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / numeric / conversion / doc / requirements.qbk
CommitLineData
7c673cae
FG
1[/
2 Boost.Optional
3
4 Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
5
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE_1_0.txt or copy at
8 http://www.boost.org/LICENSE_1_0.txt)
9]
10
11[section Type Requirements and User-defined-types support]
12
13[section Type Requirements]
14
15Both arithmetic (built-in) and user-defined numeric types require proper
16specialization of `std::numeric_limits<>` (that is, with (in-class) integral
17constants).
18
19The library uses `std::numeric_limits<T>::is_specialized` to detect whether
20the type is builtin or user defined, and `std::numeric_limits<T>::is_integer`,
21`std::numeric_limits<T>::is_signed` to detect whether the type is integer
22or floating point; and whether it is signed/unsigned.
23
24The default `Float2IntRounder` policies uses unqualified calls to functions
25`floor()` and `ceil()`; but the standard functions are introduced in scope
26by a using directive:
27
28 using std::floor ; return floor(s);
29
30Therefore, for builtin arithmetic types, the std functions will be used.
31User defined types should provide overloaded versions of these functions in
32order to use the default rounder policies. If these overloads are defined
33within a user namespace argument dependent lookup (ADL) should find them,
34but if your compiler has a weak ADL you might need to put these functions
35some place else or write your own rounder policy.
36
37The default `Trunc<>` rounder policy needs to determine if the source value
38is positive or not, and for this it evaluates the expression
39`s < static_cast<S>(0)`. Therefore, user defined types require a visible
40`operator<` in order to use the `Trunc<>` policy (the default).
41
42
43[endsect]
44
45[section UDT's special semantics]
46
47[heading Conversion Traits]
48
49If a User Defined Type is involved in a conversion, it is ['assumed] that
50the UDT has [link boost_numericconversion.definitions.range_and_precision wider range]
51than any built-in type, and consequently the values
52of some `converter_traits<>` members are hardwired regardless of the reality.
53The following table summarizes this:
54
55* `Target=`['UDT] and `Source=`['built-in]
56 * `subranged=false`
57 * `supertype=Target`
58 * `subtype=Source`
59* `Target=`['built-in] and `Source=`['UDT]
60 * `subranged=true`
61 * `supertype=Source`
62 * `subtype=Target`
63
64* `Target=`['UDT] and `Source=`['UDT]
65 * `subranged=false`
66 * `supertype=Target`
67 * `subtype=Source`
68
69
70The `Traits` member `udt_mixture` can be used to detect whether a UDT is involved
71and to infer the validity of the other members as shown above.
72
73[heading Range Checking]
74
75Because User Defined Numeric Types might have peculiar ranges (such as an
76unbounded range), this library does not attempt to supply a meaningful range
77checking logic when UDTs are involved in a conversion. Therefore, if either
78Target or Source are not built-in types, the bundled range checking of the
79`converter<>` function object is automatically disabled. However, it is possible
80to supply a user-defined range-checker. See
81[link boost_numericconversion.type_requirements_and_user_defined_types_support.special_policies Special Policies]
82
83[endsect]
84
85[section Special Policies]
86
87There are two components of the `converter<>` class that might require special
88behavior if User Defined Numeric Types are involved: the Range Checking and the
89Raw Conversion.
90
91When both Target and Source are built-in types, the converter class uses an internal
92range checking logic which is optimized and customized for the combined properties
93of the types.
94
95However, this internal logic is disabled when either type is User Defined.
96In this case, the user can specify an ['external] range checking policy which will be
97used in place of the internal code. See
98[link boost_numericconversion.type_requirements_and_user_defined_types_support.udts_with_numeric_cast numeric_cast_traits]
99for details on using UDTs with `numeric_cast`.
100
101The converter class performs the actual conversion using a Raw Converter policy.
102The default raw converter simply performs a `static_cast<Target>(source)`.
103
104However, if the a UDT is involved, the `static_cast` might not work. In this case,
105the user can implement and pass a different raw converter policy.
106See [link boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter RawConverter] policy for details.
107
108[endsect]
109
110[section UDTs with numeric_cast]
111
112In order to employ UDTs with `numeric_cast`, the user should define
113a `numeric_cast_traits` specialization on the UDT for each conversion.
114Here is an example of specializations for converting between the UDT
115and any other type:
116
117 namespace boost { namespace numeric {
118 template <typename Source>
119 struct numeric_cast_traits<UDT, Source>
120 {
121 typedef conversion_traits<UDT, Source> conv_traits;
122
123 //! The following are required:
124 typedef YourOverflowHandlerPolicy overflow_policy;
125 typedef YourRangeCheckerPolicy<conv_traits> range_checking_policy;
126 typedef YourFloat2IntRounderPolicy<Source> rounding_policy;
127 };
128 template <typename Target>
129 struct numeric_cast_traits<Target, UDT>
130 {
131 typedef conversion_traits<Target, UDT> conv_traits;
132
133 //! The following are required:
134 typedef YourOverflowHandlerPolicy overflow_policy;
135 typedef YourRangeCheckerPolicy<conv_traits> range_checking_policy;
136 typedef YourFloat2IntRounderPolicy<UDT> rounding_policy;
137 };
138 }}//namespace boost::numeric;
139
140These specializations are already defined with default values for the built-in
141numeric types. It is possible to disable the generation of specializations for
142built-in types by defining `BOOST_NUMERIC_CONVERSION_RELAX_BUILT_IN_CAST_TRAITS`.
143For details on defining custom policies see [link boost_numericconversion.numeric_converter_policy_classes Converter Policies].
144
145Here is a full example of how to define a custom UDT for use with `numeric_cast`:
146
147 //! Define a simple custom number
148 struct Double
149 : boost::ordered_field_operators
150 <
151 Double
152 , boost::ordered_field_operators2< Double, long double
153 , boost::ordered_field_operators2< Double, double
154 , boost::ordered_field_operators2< Double, float
155 , boost::ordered_field_operators2< Double, int
156 , boost::ordered_field_operators2< Double, unsigned int
157 , boost::ordered_field_operators2< Double, long
158 , boost::ordered_field_operators2< Double, unsigned long
159 , boost::ordered_field_operators2< Double, long long
160 , boost::ordered_field_operators2< Double, unsigned long long
161 , boost::ordered_field_operators2< Double, char
162 , boost::ordered_field_operators2< Double, unsigned char
163 , boost::ordered_field_operators2< Double, short
164 , boost::ordered_field_operators2< Double, unsigned short
165 > > > > > > > > > > > > > >
166 {
167 Double()
168 : v(0)
169 {}
170
171 template <typename T>
172 explicit Double( T v )
173 : v(static_cast<double>(v))
174 {}
175
176 template <typename T>
177 Double& operator= ( T t )
178 {
179 v = static_cast<double>(t);
180 return *this;
181 }
182
183 bool operator < ( const Double& rhs ) const
184 {
185 return v < rhs.v;
186 }
187
188 template <typename T>
189 bool operator < ( T rhs ) const
190 {
191 return v < static_cast<double>(rhs);
192 }
193
194 bool operator > ( const Double& rhs ) const
195 {
196 return v > rhs.v;
197 }
198
199 template <typename T>
200 bool operator > ( T rhs ) const
201 {
202 return v > static_cast<double>(rhs);
203 }
204
205 bool operator ==( const Double& rhs ) const
206 {
207 return v == rhs.v;
208 }
209
210 template <typename T>
211 bool operator == ( T rhs ) const
212 {
213 return v == static_cast<double>(rhs);
214 }
215
216 bool operator !() const
217 {
218 return v == 0;
219 }
220
221 Double operator -() const
222 {
223 return Double(-v);
224 }
225
226 Double& operator +=( const Double& t )
227 {
228 v += t.v;
229 return *this;
230 }
231
232 template <typename T>
233 Double& operator +=( T t )
234 {
235 v += static_cast<double>(t);
236 return *this;
237 }
238
239 Double& operator -=( const Double& t )
240 {
241 v -= t.v;
242 return *this;
243 }
244
245 template <typename T>
246 Double& operator -=( T t )
247 {
248 v -= static_cast<double>(t);
249 return *this;
250 }
251
252 Double& operator *= ( const Double& factor )
253 {
254 v *= factor.v;
255 return *this;
256 }
257
258 template <typename T>
259 Double& operator *=( T t )
260 {
261 v *= static_cast<double>(t);
262 return *this;
263 }
264
265 Double& operator /= (const Double& divisor)
266 {
267 v /= divisor.v;
268 return *this;
269 }
270
271 template <typename T>
272 Double& operator /=( T t )
273 {
274 v /= static_cast<double>(t);
275 return (*this);
276 }
277
278 double v;
279 };
280
281 //! Define numeric_limits for the custom type.
282 namespace std
283 {
284 template<>
285 class numeric_limits<Double> : public numeric_limits<double>
286 {
287 public:
288
289 //! Limit our Double to a range of +/- 100.0
290 static Double (min)()
291 {
292 return Double(1.e-2);
293 }
294
295 static Double (max)()
296 {
297 return Double(1.e2);
298 }
299
300 static Double epsilon()
301 {
302 return Double( std::numeric_limits<double>::epsilon() );
303 }
304 };
305 }
306
307 //! Define range checking and overflow policies.
308 namespace custom
309 {
310 //! Define a custom range checker
311 template<typename Traits, typename OverFlowHandler>
312 struct range_checker
313 {
314 typedef typename Traits::argument_type argument_type ;
315 typedef typename Traits::source_type S;
316 typedef typename Traits::target_type T;
317
318 //! Check range of integral types.
319 static boost::numeric::range_check_result out_of_range( argument_type s )
320 {
321 using namespace boost::numeric;
322 if( s > bounds<T>::highest() )
323 return cPosOverflow;
324 else if( s < bounds<T>::lowest() )
325 return cNegOverflow;
326 else
327 return cInRange;
328 }
329
330 static void validate_range ( argument_type s )
331 {
332 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_bounded );
333 OverFlowHandler()( out_of_range(s) );
334 }
335 };
336
337 //! Overflow handler
338 struct positive_overflow{};
339 struct negative_overflow{};
340
341 struct overflow_handler
342 {
343 void operator() ( boost::numeric::range_check_result r )
344 {
345 using namespace boost::numeric;
346 if( r == cNegOverflow )
347 throw negative_overflow() ;
348 else if( r == cPosOverflow )
349 throw positive_overflow() ;
350 }
351 };
352
353 //! Define a rounding policy and specialize on the custom type.
354 template<class S>
355 struct Ceil : boost::numeric::Ceil<S>{};
356
357 template<>
358 struct Ceil<Double>
359 {
360 typedef Double source_type;
361
362 typedef Double const& argument_type;
363
364 static source_type nearbyint ( argument_type s )
365 {
366 #if !defined(BOOST_NO_STDC_NAMESPACE)
367 using std::ceil ;
368 #endif
369 return Double( ceil(s.v) );
370 }
371
372 typedef boost::mpl::integral_c< std::float_round_style, std::round_toward_infinity> round_style;
373 };
374
375 //! Define a rounding policy and specialize on the custom type.
376 template<class S>
377 struct Trunc: boost::numeric::Trunc<S>{};
378
379 template<>
380 struct Trunc<Double>
381 {
382 typedef Double source_type;
383
384 typedef Double const& argument_type;
385
386 static source_type nearbyint ( argument_type s )
387 {
388 #if !defined(BOOST_NO_STDC_NAMESPACE)
389 using std::floor;
390 #endif
391 return Double( floor(s.v) );
392 }
393
394 typedef boost::mpl::integral_c< std::float_round_style, std::round_toward_zero> round_style;
395 };
396 }//namespace custom;
397
398 namespace boost { namespace numeric {
399
400 //! Define the numeric_cast_traits specializations on the custom type.
401 template <typename S>
402 struct numeric_cast_traits<Double, S>
403 {
404 typedef custom::overflow_handler overflow_policy;
405 typedef custom::range_checker
406 <
407 boost::numeric::conversion_traits<Double, S>
408 , overflow_policy
409 > range_checking_policy;
410 typedef boost::numeric::Trunc<S> rounding_policy;
411 };
412
413 template <typename T>
414 struct numeric_cast_traits<T, Double>
415 {
416 typedef custom::overflow_handler overflow_policy;
417 typedef custom::range_checker
418 <
419 boost::numeric::conversion_traits<T, Double>
420 , overflow_policy
421 > range_checking_policy;
422 typedef custom::Trunc<Double> rounding_policy;
423 };
424
425 //! Define the conversion from the custom type to built-in types and vice-versa.
426 template<typename T>
427 struct raw_converter< conversion_traits< T, Double > >
428 {
429 static T low_level_convert ( const Double& n )
430 {
431 return static_cast<T>( n.v );
432 }
433 };
434
435 template<typename S>
436 struct raw_converter< conversion_traits< Double, S > >
437 {
438 static Double low_level_convert ( const S& n )
439 {
440 return Double(n);
441 }
442 };
443 }}//namespace boost::numeric;
444
445[endsect]
446
447[endsect]
448