source: NonGTP/Boost/boost/numeric/ublas/traits.hpp @ 857

Revision 857, 18.7 KB checked in by igarcia, 18 years ago (diff)
Line 
1//
2//  Copyright (c) 2000-2002
3//  Joerg Walter, Mathias Koch
4//
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.
12//
13//  The authors gratefully acknowledge the support of
14//  GeNeSys mbH & Co. KG in producing this work.
15//
16
17#ifndef _BOOST_UBLAS_TRAITS_
18#define _BOOST_UBLAS_TRAITS_
19
20#include <iterator>
21#include <complex>
22#include <cmath>
23
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>
27
28
29namespace boost { namespace numeric { namespace ublas {
30
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
43            );
44
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;
49    };
50
51
52        // Type traits - generic numeric properties and functions
53    template<class T>
54    struct type_traits;
55       
56    // Define properties for a generic scalar type
57    template<class T>
58    struct scalar_traits {
59        typedef scalar_traits<T> self_type;
60        typedef T value_type;
61        typedef const T &const_reference;
62        typedef T &reference;
63
64        typedef T real_type;
65        typedef real_type precision_type;       // we do not know what type has more precision then the real_type
66
67        static const unsigned plus_complexity = 1;
68        static const unsigned multiplies_complexity = 1;
69
70        static
71        BOOST_UBLAS_INLINE
72        real_type real (const_reference t) {
73                return t;
74        }
75        static
76        BOOST_UBLAS_INLINE
77        real_type imag (const_reference /*t*/) {
78                return 0;
79        }
80        static
81        BOOST_UBLAS_INLINE
82        value_type conj (const_reference t) {
83                return t;
84        }
85
86        static
87        BOOST_UBLAS_INLINE
88        real_type abs (const_reference t) {
89            return std::abs (t);
90        }
91        static
92        BOOST_UBLAS_INLINE
93        value_type sqrt (const_reference t) {
94            return std::sqrt (t);
95        }
96
97        static
98        BOOST_UBLAS_INLINE
99        real_type norm_1 (const_reference t) {
100            return self_type::abs (t);
101        }
102        static
103        BOOST_UBLAS_INLINE
104        real_type norm_2 (const_reference t) {
105            return self_type::abs (t);
106        }
107        static
108        BOOST_UBLAS_INLINE
109        real_type norm_inf (const_reference t) {
110            return self_type::abs (t);
111        }
112
113        static
114        BOOST_UBLAS_INLINE
115        bool equals (const_reference t1, const_reference t2) {
116            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
117                   (std::max) ((std::max) (self_type::norm_inf (t1),
118                                       self_type::norm_inf (t2)),
119                             BOOST_UBLAS_TYPE_CHECK_MIN);
120        }
121    };
122   
123    // Define default type traits, assume T is a scalar type
124    template<class T>
125    struct type_traits : scalar_traits <T> {
126        typedef type_traits<T> self_type;
127        typedef T value_type;
128        typedef const T &const_reference;
129        typedef T &reference;
130
131        typedef T real_type;
132        typedef real_type precision_type;
133        static const unsigned multiplies_complexity = 1;
134
135    };
136
137    // Define real type traits
138    template<>
139    struct type_traits<float> : scalar_traits<float> {
140        typedef type_traits<float> self_type;
141        typedef float value_type;
142        typedef const value_type &const_reference;
143        typedef value_type &reference;
144        typedef value_type real_type;
145        typedef double precision_type;
146    };
147    template<>
148    struct type_traits<double> : scalar_traits<double> {
149        typedef type_traits<double> self_type;
150        typedef double value_type;
151        typedef const value_type &const_reference;
152        typedef value_type &reference;
153        typedef value_type real_type;
154        typedef long double precision_type;
155    };
156    template<>
157    struct type_traits<long double>  : scalar_traits<long double> {
158        typedef type_traits<long double> self_type;
159        typedef long double value_type;
160        typedef const value_type &const_reference;
161        typedef value_type &reference;
162        typedef value_type real_type;
163        typedef value_type precision_type;
164    };
165
166    // Define properties for a generic complex type
167    template<class T>
168    struct complex_traits {
169        typedef complex_traits<T> self_type;
170        typedef T value_type;
171        typedef const T &const_reference;
172        typedef T &reference;
173
174        typedef typename T::value_type real_type;
175        typedef real_type precision_type;       // we do not know what type has more precision then the real_type
176
177        static const unsigned plus_complexity = 2;
178        static const unsigned multiplies_complexity = 6;
179
180        static
181        BOOST_UBLAS_INLINE
182        real_type real (const_reference t) {
183                return std::real (t);
184        }
185        static
186        BOOST_UBLAS_INLINE
187        real_type imag (const_reference t) {
188                return std::imag (t);
189        }
190        static
191        BOOST_UBLAS_INLINE
192        value_type conj (const_reference t) {
193                return std::conj (t);
194        }
195
196        static
197        BOOST_UBLAS_INLINE
198        real_type abs (const_reference t) {
199                return std::abs (t);
200        }
201        static
202        BOOST_UBLAS_INLINE
203        value_type sqrt (const_reference t) {
204                return std::sqrt (t);
205        }
206
207        static
208        BOOST_UBLAS_INLINE
209        real_type norm_1 (const_reference t) {
210            return type_traits<real_type>::abs (self_type::real (t)) +
211                   type_traits<real_type>::abs (self_type::imag (t));
212        }
213        static
214        BOOST_UBLAS_INLINE
215        real_type norm_2 (const_reference t) {
216            return self_type::abs (t);
217        }
218        static
219        BOOST_UBLAS_INLINE
220        real_type norm_inf (const_reference t) {
221            return (std::max) (type_traits<real_type>::abs (self_type::real (t)),
222                             type_traits<real_type>::abs (self_type::imag (t)));
223        }
224
225        static
226        BOOST_UBLAS_INLINE
227        bool equals (const_reference t1, const_reference t2) {
228            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
229                   (std::max) ((std::max) (self_type::norm_inf (t1),
230                                       self_type::norm_inf (t2)),
231                             BOOST_UBLAS_TYPE_CHECK_MIN);
232        }
233    };
234   
235    // Define complex type traits
236    template<>
237    struct type_traits<std::complex<float> > : complex_traits<std::complex<float> >{
238        typedef type_traits<std::complex<float> > self_type;
239        typedef std::complex<float> value_type;
240        typedef const value_type &const_reference;
241        typedef value_type &reference;
242        typedef float real_type;
243        typedef std::complex<double> precision_type;
244
245    };
246    template<>
247    struct type_traits<std::complex<double> > : complex_traits<std::complex<double> >{
248        typedef type_traits<std::complex<double> > self_type;
249        typedef std::complex<double> value_type;
250        typedef const value_type &const_reference;
251        typedef value_type &reference;
252        typedef double real_type;
253        typedef std::complex<long double> precision_type;
254    };
255    template<>
256    struct type_traits<std::complex<long double> > : complex_traits<std::complex<long double> > {
257        typedef type_traits<std::complex<long double> > self_type;
258        typedef std::complex<long double> value_type;
259        typedef const value_type &const_reference;
260        typedef value_type &reference;
261        typedef long double real_type;
262        typedef value_type precision_type;
263    };
264
265#ifdef BOOST_UBLAS_USE_INTERVAL
266    // Define properties for a generic scalar interval type
267    template<class T>
268    struct scalar_interval_type_traits : scalar_type_traits<T> {
269        typedef scalar_interval_type_traits<T> self_type;
270        typedef boost::numeric::interval<float> value_type;
271        typedef const value_type &const_reference;
272        typedef value_type &reference;
273        typedef value_type real_type;
274        typedef real_type precision_type;       // we do not know what type has more precision then the real_type
275
276        static const unsigned plus_complexity = 1;
277        static const unsigned multiplies_complexity = 1;
278
279        static
280        BOOST_UBLAS_INLINE
281        real_type abs (const_reference t) {
282            return boost::numeric::abs (t);
283        }
284        static
285        BOOST_UBLAS_INLINE
286        value_type sqrt (const_reference t) {
287            return boost::numeric::sqrt (t);
288        }
289
290        static
291        BOOST_UBLAS_INLINE
292        real_type norm_1 (const_reference t) {
293            return self_type::abs (t);
294        }
295        static
296        BOOST_UBLAS_INLINE
297        real_type norm_2 (const_reference t) {
298            return self_type::abs (t);
299        }
300        static
301        BOOST_UBLAS_INLINE
302        real_type norm_inf (const_reference t) {
303            return self_type::abs (t);
304        }
305
306        static
307        BOOST_UBLAS_INLINE
308        bool equals (const_reference t1, const_reference t2) {
309            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
310                   (std::max) ((std::max) (self_type::norm_inf (t1),
311                                       self_type::norm_inf (t2)),
312                             BOOST_UBLAS_TYPE_CHECK_MIN);
313        }
314    };
315
316    // Define scalar interval type traits
317    template<>
318    struct type_traits<boost::numeric::interval<float> > : scalar_interval_type_traits<boost::numeric::interval<float> > {
319        typedef type_traits<boost::numeric::interval<float> > self_type;
320        typedef boost::numeric::interval<float> value_type;
321        typedef const value_type &const_reference;
322        typedef value_type &reference;
323        typedef value_type real_type;
324        typedef boost::numeric::interval<double> precision_type;
325
326    };
327    template<>
328    struct type_traits<boost::numeric::interval<double> > : scalar_interval_type_traits<boost::numeric::interval<double> > {
329        typedef type_traits<boost::numeric::interval<double> > self_type;
330        typedef boost::numeric::interval<double> value_type;
331        typedef const value_type &const_reference;
332        typedef value_type &reference;
333        typedef value_type real_type;
334        typedef boost::numeric::interval<long double> precision_type;
335    };
336    template<>
337    struct type_traits<boost::numeric::interval<long double> > : scalar_interval_type_traits<boost::numeric::interval<long double> > {
338        typedef type_traits<boost::numeric::interval<long double> > self_type;
339        typedef boost::numeric::interval<long double> value_type;
340        typedef const value_type &const_reference;
341        typedef value_type &reference;
342        typedef value_type real_type;
343        typedef value_type precision_type;
344    };
345
346#endif
347
348
349    // Storage tags -- hierarchical definition of storage characteristics
350
351    struct unknown_storage_tag {};
352    struct sparse_proxy_tag: public unknown_storage_tag {};
353    struct sparse_tag: public sparse_proxy_tag {};
354    struct packed_proxy_tag: public sparse_proxy_tag {};
355    struct packed_tag: public packed_proxy_tag {};
356    struct dense_proxy_tag: public packed_proxy_tag {};
357    struct dense_tag: public dense_proxy_tag {};
358
359    template<class S1, class S2>
360    struct storage_restrict_traits {
361        typedef S1 storage_category;
362    };
363
364    template<>
365    struct storage_restrict_traits<sparse_tag, dense_proxy_tag> {
366        typedef sparse_proxy_tag storage_category;
367    };
368    template<>
369    struct storage_restrict_traits<sparse_tag, packed_proxy_tag> {
370        typedef sparse_proxy_tag storage_category;
371    };
372    template<>
373    struct storage_restrict_traits<sparse_tag, sparse_proxy_tag> {
374        typedef sparse_proxy_tag storage_category;
375    };
376
377    template<>
378    struct storage_restrict_traits<packed_tag, dense_proxy_tag> {
379        typedef packed_proxy_tag storage_category;
380    };
381    template<>
382    struct storage_restrict_traits<packed_tag, packed_proxy_tag> {
383        typedef packed_proxy_tag storage_category;
384    };
385    template<>
386    struct storage_restrict_traits<packed_tag, sparse_proxy_tag> {
387        typedef sparse_proxy_tag storage_category;
388    };
389
390    template<>
391    struct storage_restrict_traits<packed_proxy_tag, sparse_proxy_tag> {
392        typedef sparse_proxy_tag storage_category;
393    };
394
395    template<>
396    struct storage_restrict_traits<dense_tag, dense_proxy_tag> {
397        typedef dense_proxy_tag storage_category;
398    };
399    template<>
400    struct storage_restrict_traits<dense_tag, packed_proxy_tag> {
401        typedef packed_proxy_tag storage_category;
402    };
403    template<>
404    struct storage_restrict_traits<dense_tag, sparse_proxy_tag> {
405        typedef sparse_proxy_tag storage_category;
406    };
407
408    template<>
409    struct storage_restrict_traits<dense_proxy_tag, packed_proxy_tag> {
410        typedef packed_proxy_tag storage_category;
411    };
412    template<>
413    struct storage_restrict_traits<dense_proxy_tag, sparse_proxy_tag> {
414        typedef sparse_proxy_tag storage_category;
415    };
416
417
418    // Iterator tags -- hierarchical definition of storage characteristics
419
420    struct sparse_bidirectional_iterator_tag : public std::bidirectional_iterator_tag {};
421    struct packed_random_access_iterator_tag : public std::random_access_iterator_tag {};
422    struct dense_random_access_iterator_tag : public packed_random_access_iterator_tag {};
423
424    // Thanks to Kresimir Fresl for convincing Comeau with iterator_base_traits ;-)
425    template<class IC>
426    struct iterator_base_traits {};
427
428    template<>
429    struct iterator_base_traits<std::forward_iterator_tag> {
430        template<class I, class T>
431        struct iterator_base {
432            typedef forward_iterator_base<std::forward_iterator_tag, I, T> type;
433        };
434    };
435
436    template<>
437    struct iterator_base_traits<std::bidirectional_iterator_tag> {
438        template<class I, class T>
439        struct iterator_base {
440            typedef bidirectional_iterator_base<std::bidirectional_iterator_tag, I, T> type;
441        };
442    };
443    template<>
444    struct iterator_base_traits<sparse_bidirectional_iterator_tag> {
445        template<class I, class T>
446        struct iterator_base {
447            typedef bidirectional_iterator_base<sparse_bidirectional_iterator_tag, I, T> type;
448        };
449    };
450
451    template<>
452    struct iterator_base_traits<std::random_access_iterator_tag> {
453        template<class I, class T>
454        struct iterator_base {
455            typedef random_access_iterator_base<std::random_access_iterator_tag, I, T> type;
456        };
457    };
458    template<>
459    struct iterator_base_traits<packed_random_access_iterator_tag> {
460        template<class I, class T>
461        struct iterator_base {
462            typedef random_access_iterator_base<packed_random_access_iterator_tag, I, T> type;
463        };
464    };
465    template<>
466    struct iterator_base_traits<dense_random_access_iterator_tag> {
467        template<class I, class T>
468        struct iterator_base {
469            typedef random_access_iterator_base<dense_random_access_iterator_tag, I, T> type;
470        };
471    };
472
473    template<class I1, class I2>
474    struct iterator_restrict_traits {
475        typedef I1 iterator_category;
476    };
477
478    template<>
479    struct iterator_restrict_traits<packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
480        typedef sparse_bidirectional_iterator_tag iterator_category;
481    };
482    template<>
483    struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag> {
484        typedef sparse_bidirectional_iterator_tag iterator_category;
485    };
486
487    template<>
488    struct iterator_restrict_traits<dense_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
489        typedef sparse_bidirectional_iterator_tag iterator_category;
490    };
491    template<>
492    struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, dense_random_access_iterator_tag> {
493        typedef sparse_bidirectional_iterator_tag iterator_category;
494    };
495
496    template<>
497    struct iterator_restrict_traits<dense_random_access_iterator_tag, packed_random_access_iterator_tag> {
498        typedef packed_random_access_iterator_tag iterator_category;
499    };
500    template<>
501    struct iterator_restrict_traits<packed_random_access_iterator_tag, dense_random_access_iterator_tag> {
502        typedef packed_random_access_iterator_tag iterator_category;
503    };
504
505    template<class I>
506    BOOST_UBLAS_INLINE
507    void increment (I &it, const I &it_end, typename I::difference_type compare, packed_random_access_iterator_tag) {
508        it += (std::min) (compare, it_end - it);
509    }
510    template<class I>
511    BOOST_UBLAS_INLINE
512    void increment (I &it, const I &/* it_end */, typename I::difference_type /* compare */, sparse_bidirectional_iterator_tag) {
513        ++ it;
514    }
515    template<class I>
516    BOOST_UBLAS_INLINE
517    void increment (I &it, const I &it_end, typename I::difference_type compare) {
518        increment (it, it_end, compare, typename I::iterator_category ());
519    }
520
521    template<class I>
522    BOOST_UBLAS_INLINE
523    void increment (I &it, const I &it_end) {
524#if BOOST_UBLAS_TYPE_CHECK
525        I cit (it);
526        while (cit != it_end) {
527            BOOST_UBLAS_CHECK (*cit == typename I::value_type/*zero*/(), internal_logic ());
528            ++ cit;
529        }
530#endif
531        it = it_end;
532    }
533
534}}}
535
536#endif
Note: See TracBrowser for help on using the repository browser.