Update contrib.
2 // Copyright (c) 2000-2002
3 // Joerg Walter, Mathias Koch
5 // Permission to use, copy, modify, distribute and sell this software
6 // and its documentation for any purpose is hereby granted without fee,
7 // provided that the above copyright notice appear in all copies and
8 // that both that copyright notice and this permission notice appear
9 // in supporting documentation. The authors make no representations
10 // about the suitability of this software for any purpose.
11 // It is provided "as is" without express or implied warranty.
13 // The authors gratefully acknowledge the support of
14 // GeNeSys mbH & Co. KG in producing this work.
17 #ifndef _BOOST_UBLAS_TRAITS_
18 #define _BOOST_UBLAS_TRAITS_
24 #include <boost/numeric/ublas/detail/config.hpp>
25 #include <boost/numeric/ublas/detail/iterator.hpp>
26 #include <boost/numeric/ublas/detail/returntype_deduction.hpp>
29 namespace boost { namespace numeric { namespace ublas {
31 // Use Joel de Guzman's return type deduction
32 // uBLAS assumes a common return type for all binary arithmetic operators
33 template<class X, class Y>
34 struct promote_traits {
35 typedef type_deduction_detail::base_result_of<X, Y> base_type;
36 static typename base_type::x_type x;
37 static typename base_type::y_type y;
38 static const std::size_t size = sizeof (
39 type_deduction_detail::test<
40 typename base_type::x_type
41 , typename base_type::y_type
42 >(x + y) // Use x+y to stand of all the arithmetic actions
45 static const std::size_t index = (size / sizeof (char)) - 1;
46 typedef typename mpl::at_c<
47 typename base_type::types, index>::type id;
48 typedef typename id::type promote_type;
52 // Type traits - generic numeric properties and functions
56 // Define properties for a generic scalar type
58 struct scalar_traits {
59 typedef scalar_traits<T> self_type;
61 typedef const T &const_reference;
65 typedef real_type precision_type; // we do not know what type has more precision then the real_type
67 static const unsigned plus_complexity = 1;
68 static const unsigned multiplies_complexity = 1;
72 real_type real (const_reference t) {
77 real_type imag (const_reference /*t*/) {
82 value_type conj (const_reference t) {
88 real_type type_abs (const_reference t) {
89 return std::abs (t); // must use explict std:: as bultin types are not in std namespace
93 value_type type_sqrt (const_reference t) {
94 // force a type conversion back to value_type for intgral types
95 return value_type (std::sqrt (t)); // must use explict std:: as bultin types are not in std namespace
100 real_type norm_1 (const_reference t) {
101 return self_type::type_abs (t);
105 real_type norm_2 (const_reference t) {
106 return self_type::type_abs (t);
110 real_type norm_inf (const_reference t) {
111 return self_type::type_abs (t);
116 bool equals (const_reference t1, const_reference t2) {
117 return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
118 (std::max) ((std::max) (self_type::norm_inf (t1),
119 self_type::norm_inf (t2)),
120 BOOST_UBLAS_TYPE_CHECK_MIN);
124 // Define default type traits, assume T is a scalar type
126 struct type_traits : scalar_traits <T> {
127 typedef type_traits<T> self_type;
128 typedef T value_type;
129 typedef const T &const_reference;
130 typedef T &reference;
133 typedef real_type precision_type;
134 static const unsigned multiplies_complexity = 1;
138 // Define real type traits
140 struct type_traits<float> : scalar_traits<float> {
141 typedef type_traits<float> self_type;
142 typedef float value_type;
143 typedef const value_type &const_reference;
144 typedef value_type &reference;
145 typedef value_type real_type;
146 typedef double precision_type;
149 struct type_traits<double> : scalar_traits<double> {
150 typedef type_traits<double> self_type;
151 typedef double value_type;
152 typedef const value_type &const_reference;
153 typedef value_type &reference;
154 typedef value_type real_type;
155 typedef long double precision_type;
158 struct type_traits<long double> : scalar_traits<long double> {
159 typedef type_traits<long double> self_type;
160 typedef long double value_type;
161 typedef const value_type &const_reference;
162 typedef value_type &reference;
163 typedef value_type real_type;
164 typedef value_type precision_type;
167 // Define properties for a generic complex type
169 struct complex_traits {
170 typedef complex_traits<T> self_type;
171 typedef T value_type;
172 typedef const T &const_reference;
173 typedef T &reference;
175 typedef typename T::value_type real_type;
176 typedef real_type precision_type; // we do not know what type has more precision then the real_type
178 static const unsigned plus_complexity = 2;
179 static const unsigned multiplies_complexity = 6;
183 real_type real (const_reference t) {
184 return std::real (t);
188 real_type imag (const_reference t) {
189 return std::imag (t);
193 value_type conj (const_reference t) {
194 return std::conj (t);
199 real_type type_abs (const_reference t) {
204 value_type type_sqrt (const_reference t) {
210 real_type norm_1 (const_reference t) {
211 return type_traits<real_type>::type_abs (self_type::real (t)) +
212 type_traits<real_type>::type_abs (self_type::imag (t));
216 real_type norm_2 (const_reference t) {
217 return self_type::type_abs (t);
221 real_type norm_inf (const_reference t) {
222 return (std::max) (type_traits<real_type>::type_abs (self_type::real (t)),
223 type_traits<real_type>::type_abs (self_type::imag (t)));
228 bool equals (const_reference t1, const_reference t2) {
229 return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
230 (std::max) ((std::max) (self_type::norm_inf (t1),
231 self_type::norm_inf (t2)),
232 BOOST_UBLAS_TYPE_CHECK_MIN);
236 // Define complex type traits
238 struct type_traits<std::complex<float> > : complex_traits<std::complex<float> >{
239 typedef type_traits<std::complex<float> > self_type;
240 typedef std::complex<float> value_type;
241 typedef const value_type &const_reference;
242 typedef value_type &reference;
243 typedef float real_type;
244 typedef std::complex<double> precision_type;
248 struct type_traits<std::complex<double> > : complex_traits<std::complex<double> >{
249 typedef type_traits<std::complex<double> > self_type;
250 typedef std::complex<double> value_type;
251 typedef const value_type &const_reference;
252 typedef value_type &reference;
253 typedef double real_type;
254 typedef std::complex<long double> precision_type;
257 struct type_traits<std::complex<long double> > : complex_traits<std::complex<long double> > {
258 typedef type_traits<std::complex<long double> > self_type;
259 typedef std::complex<long double> value_type;
260 typedef const value_type &const_reference;
261 typedef value_type &reference;
262 typedef long double real_type;
263 typedef value_type precision_type;
266 #ifdef BOOST_UBLAS_USE_INTERVAL
267 // Define properties for a generic scalar interval type
269 struct scalar_interval_type_traits : scalar_type_traits<T> {
270 typedef scalar_interval_type_traits<T> self_type;
271 typedef boost::numeric::interval<float> value_type;
272 typedef const value_type &const_reference;
273 typedef value_type &reference;
274 typedef value_type real_type;
275 typedef real_type precision_type; // we do not know what type has more precision then the real_type
277 static const unsigned plus_complexity = 1;
278 static const unsigned multiplies_complexity = 1;
282 real_type type_abs (const_reference t) {
287 value_type type_sqrt (const_reference t) {
293 real_type norm_1 (const_reference t) {
294 return self_type::type_abs (t);
298 real_type norm_2 (const_reference t) {
299 return self_type::type_abs (t);
303 real_type norm_inf (const_reference t) {
304 return self_type::type_abs (t);
309 bool equals (const_reference t1, const_reference t2) {
310 return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
311 (std::max) ((std::max) (self_type::norm_inf (t1),
312 self_type::norm_inf (t2)),
313 BOOST_UBLAS_TYPE_CHECK_MIN);
317 // Define scalar interval type traits
319 struct type_traits<boost::numeric::interval<float> > : scalar_interval_type_traits<boost::numeric::interval<float> > {
320 typedef type_traits<boost::numeric::interval<float> > self_type;
321 typedef boost::numeric::interval<float> value_type;
322 typedef const value_type &const_reference;
323 typedef value_type &reference;
324 typedef value_type real_type;
325 typedef boost::numeric::interval<double> precision_type;
329 struct type_traits<boost::numeric::interval<double> > : scalar_interval_type_traits<boost::numeric::interval<double> > {
330 typedef type_traits<boost::numeric::interval<double> > self_type;
331 typedef boost::numeric::interval<double> value_type;
332 typedef const value_type &const_reference;
333 typedef value_type &reference;
334 typedef value_type real_type;
335 typedef boost::numeric::interval<long double> precision_type;
338 struct type_traits<boost::numeric::interval<long double> > : scalar_interval_type_traits<boost::numeric::interval<long double> > {
339 typedef type_traits<boost::numeric::interval<long double> > self_type;
340 typedef boost::numeric::interval<long double> value_type;
341 typedef const value_type &const_reference;
342 typedef value_type &reference;
343 typedef value_type real_type;
344 typedef value_type precision_type;
350 // Storage tags -- hierarchical definition of storage characteristics
352 struct unknown_storage_tag {};
353 struct sparse_proxy_tag: public unknown_storage_tag {};
354 struct sparse_tag: public sparse_proxy_tag {};
355 struct packed_proxy_tag: public sparse_proxy_tag {};
356 struct packed_tag: public packed_proxy_tag {};
357 struct dense_proxy_tag: public packed_proxy_tag {};
358 struct dense_tag: public dense_proxy_tag {};
360 template<class S1, class S2>
361 struct storage_restrict_traits {
362 typedef S1 storage_category;
366 struct storage_restrict_traits<sparse_tag, dense_proxy_tag> {
367 typedef sparse_proxy_tag storage_category;
370 struct storage_restrict_traits<sparse_tag, packed_proxy_tag> {
371 typedef sparse_proxy_tag storage_category;
374 struct storage_restrict_traits<sparse_tag, sparse_proxy_tag> {
375 typedef sparse_proxy_tag storage_category;
379 struct storage_restrict_traits<packed_tag, dense_proxy_tag> {
380 typedef packed_proxy_tag storage_category;
383 struct storage_restrict_traits<packed_tag, packed_proxy_tag> {
384 typedef packed_proxy_tag storage_category;
387 struct storage_restrict_traits<packed_tag, sparse_proxy_tag> {
388 typedef sparse_proxy_tag storage_category;
392 struct storage_restrict_traits<packed_proxy_tag, sparse_proxy_tag> {
393 typedef sparse_proxy_tag storage_category;
397 struct storage_restrict_traits<dense_tag, dense_proxy_tag> {
398 typedef dense_proxy_tag storage_category;
401 struct storage_restrict_traits<dense_tag, packed_proxy_tag> {
402 typedef packed_proxy_tag storage_category;
405 struct storage_restrict_traits<dense_tag, sparse_proxy_tag> {
406 typedef sparse_proxy_tag storage_category;
410 struct storage_restrict_traits<dense_proxy_tag, packed_proxy_tag> {
411 typedef packed_proxy_tag storage_category;
414 struct storage_restrict_traits<dense_proxy_tag, sparse_proxy_tag> {
415 typedef sparse_proxy_tag storage_category;
419 // Iterator tags -- hierarchical definition of storage characteristics
421 struct sparse_bidirectional_iterator_tag : public std::bidirectional_iterator_tag {};
422 struct packed_random_access_iterator_tag : public std::random_access_iterator_tag {};
423 struct dense_random_access_iterator_tag : public packed_random_access_iterator_tag {};
425 // Thanks to Kresimir Fresl for convincing Comeau with iterator_base_traits ;-)
427 struct iterator_base_traits {};
430 struct iterator_base_traits<std::forward_iterator_tag> {
431 template<class I, class T>
432 struct iterator_base {
433 typedef forward_iterator_base<std::forward_iterator_tag, I, T> type;
438 struct iterator_base_traits<std::bidirectional_iterator_tag> {
439 template<class I, class T>
440 struct iterator_base {
441 typedef bidirectional_iterator_base<std::bidirectional_iterator_tag, I, T> type;
445 struct iterator_base_traits<sparse_bidirectional_iterator_tag> {
446 template<class I, class T>
447 struct iterator_base {
448 typedef bidirectional_iterator_base<sparse_bidirectional_iterator_tag, I, T> type;
453 struct iterator_base_traits<std::random_access_iterator_tag> {
454 template<class I, class T>
455 struct iterator_base {
456 typedef random_access_iterator_base<std::random_access_iterator_tag, I, T> type;
460 struct iterator_base_traits<packed_random_access_iterator_tag> {
461 template<class I, class T>
462 struct iterator_base {
463 typedef random_access_iterator_base<packed_random_access_iterator_tag, I, T> type;
467 struct iterator_base_traits<dense_random_access_iterator_tag> {
468 template<class I, class T>
469 struct iterator_base {
470 typedef random_access_iterator_base<dense_random_access_iterator_tag, I, T> type;
474 template<class I1, class I2>
475 struct iterator_restrict_traits {
476 typedef I1 iterator_category;
480 struct iterator_restrict_traits<packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
481 typedef sparse_bidirectional_iterator_tag iterator_category;
484 struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag> {
485 typedef sparse_bidirectional_iterator_tag iterator_category;
489 struct iterator_restrict_traits<dense_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
490 typedef sparse_bidirectional_iterator_tag iterator_category;
493 struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, dense_random_access_iterator_tag> {
494 typedef sparse_bidirectional_iterator_tag iterator_category;
498 struct iterator_restrict_traits<dense_random_access_iterator_tag, packed_random_access_iterator_tag> {
499 typedef packed_random_access_iterator_tag iterator_category;
502 struct iterator_restrict_traits<packed_random_access_iterator_tag, dense_random_access_iterator_tag> {
503 typedef packed_random_access_iterator_tag iterator_category;
508 void increment (I &it, const I &it_end, typename I::difference_type compare, packed_random_access_iterator_tag) {
509 it += (std::min) (compare, it_end - it);
513 void increment (I &it, const I &/* it_end */, typename I::difference_type /* compare */, sparse_bidirectional_iterator_tag) {
518 void increment (I &it, const I &it_end, typename I::difference_type compare) {
519 increment (it, it_end, compare, typename I::iterator_category ());
524 void increment (I &it, const I &it_end) {
525 #if BOOST_UBLAS_TYPE_CHECK
527 while (cit != it_end) {
528 BOOST_UBLAS_CHECK (*cit == typename I::value_type/*zero*/(), internal_logic ());