1 | // |
---|
2 | // Copyright (c) 2000-2002 |
---|
3 | // Joerg Walter, Mathias Koch |
---|
4 | // |
---|
5 | // Distributed under the Boost Software License, Version 1.0. (See |
---|
6 | // accompanying file LICENSE_1_0.txt or copy at |
---|
7 | // http://www.boost.org/LICENSE_1_0.txt) |
---|
8 | // |
---|
9 | // The authors gratefully acknowledge the support of |
---|
10 | // GeNeSys mbH & Co. KG in producing this work. |
---|
11 | // |
---|
12 | |
---|
13 | #ifndef _BOOST_UBLAS_TRAITS_ |
---|
14 | #define _BOOST_UBLAS_TRAITS_ |
---|
15 | |
---|
16 | #include <iterator> |
---|
17 | #include <complex> |
---|
18 | #include <boost/config/no_tr1/cmath.hpp> |
---|
19 | |
---|
20 | #include <boost/numeric/ublas/detail/config.hpp> |
---|
21 | #include <boost/numeric/ublas/detail/iterator.hpp> |
---|
22 | #include <boost/numeric/ublas/detail/returntype_deduction.hpp> |
---|
23 | |
---|
24 | #include <boost/type_traits.hpp> |
---|
25 | #include <complex> |
---|
26 | #include <boost/typeof/typeof.hpp> |
---|
27 | #include <boost/utility/enable_if.hpp> |
---|
28 | #include <boost/type_traits/is_float.hpp> |
---|
29 | #include <boost/type_traits/is_integral.hpp> |
---|
30 | #include <boost/mpl/and.hpp> |
---|
31 | |
---|
32 | // anonymous namespace to avoid ADL issues |
---|
33 | namespace { |
---|
34 | template<class T> T boost_numeric_ublas_sqrt (const T& t) { |
---|
35 | using namespace std; |
---|
36 | // we'll find either std::sqrt or else another version via ADL: |
---|
37 | return sqrt (t); |
---|
38 | } |
---|
39 | template<class T> T boost_numeric_ublas_abs (const T& t) { |
---|
40 | using namespace std; |
---|
41 | // we'll find either std::abs or else another version via ADL: |
---|
42 | return abs (t); |
---|
43 | } |
---|
44 | } |
---|
45 | |
---|
46 | namespace boost { namespace numeric { namespace ublas { |
---|
47 | |
---|
48 | // Use Joel de Guzman's return type deduction |
---|
49 | // uBLAS assumes a common return type for all binary arithmetic operators |
---|
50 | template<class X, class Y> |
---|
51 | struct promote_traits { |
---|
52 | typedef type_deduction_detail::base_result_of<X, Y> base_type; |
---|
53 | static typename base_type::x_type x; |
---|
54 | static typename base_type::y_type y; |
---|
55 | static const std::size_t size = sizeof ( |
---|
56 | type_deduction_detail::test< |
---|
57 | typename base_type::x_type |
---|
58 | , typename base_type::y_type |
---|
59 | >(x + y) // Use x+y to stand of all the arithmetic actions |
---|
60 | ); |
---|
61 | |
---|
62 | static const std::size_t index = (size / sizeof (char)) - 1; |
---|
63 | typedef typename mpl::at_c< |
---|
64 | typename base_type::types, index>::type id; |
---|
65 | typedef typename id::type promote_type; |
---|
66 | }; |
---|
67 | |
---|
68 | template<typename R, typename I> |
---|
69 | typename boost::enable_if< |
---|
70 | mpl::and_< |
---|
71 | boost::is_float<R>, |
---|
72 | boost::is_integral<I> |
---|
73 | >, |
---|
74 | std::complex<R> >::type inline operator+ (I in1, std::complex<R> const& in2 ) { |
---|
75 | return R (in1) + in2; |
---|
76 | } |
---|
77 | |
---|
78 | template<typename R, typename I> |
---|
79 | typename boost::enable_if< |
---|
80 | mpl::and_< |
---|
81 | boost::is_float<R>, |
---|
82 | boost::is_integral<I> |
---|
83 | >, |
---|
84 | std::complex<R> >::type inline operator+ (std::complex<R> const& in1, I in2) { |
---|
85 | return in1 + R (in2); |
---|
86 | } |
---|
87 | |
---|
88 | template<typename R, typename I> |
---|
89 | typename boost::enable_if< |
---|
90 | mpl::and_< |
---|
91 | boost::is_float<R>, |
---|
92 | boost::is_integral<I> |
---|
93 | >, |
---|
94 | std::complex<R> >::type inline operator- (I in1, std::complex<R> const& in2) { |
---|
95 | return R (in1) - in2; |
---|
96 | } |
---|
97 | |
---|
98 | template<typename R, typename I> |
---|
99 | typename boost::enable_if< |
---|
100 | mpl::and_< |
---|
101 | boost::is_float<R>, |
---|
102 | boost::is_integral<I> |
---|
103 | >, |
---|
104 | std::complex<R> >::type inline operator- (std::complex<R> const& in1, I in2) { |
---|
105 | return in1 - R (in2); |
---|
106 | } |
---|
107 | |
---|
108 | template<typename R, typename I> |
---|
109 | typename boost::enable_if< |
---|
110 | mpl::and_< |
---|
111 | boost::is_float<R>, |
---|
112 | boost::is_integral<I> |
---|
113 | >, |
---|
114 | std::complex<R> >::type inline operator* (I in1, std::complex<R> const& in2) { |
---|
115 | return R (in1) * in2; |
---|
116 | } |
---|
117 | |
---|
118 | template<typename R, typename I> |
---|
119 | typename boost::enable_if< |
---|
120 | mpl::and_< |
---|
121 | boost::is_float<R>, |
---|
122 | boost::is_integral<I> |
---|
123 | >, |
---|
124 | std::complex<R> >::type inline operator* (std::complex<R> const& in1, I in2) { |
---|
125 | return in1 * R(in2); |
---|
126 | } |
---|
127 | |
---|
128 | template<typename R, typename I> |
---|
129 | typename boost::enable_if< |
---|
130 | mpl::and_< |
---|
131 | boost::is_float<R>, |
---|
132 | boost::is_integral<I> |
---|
133 | >, |
---|
134 | std::complex<R> >::type inline operator/ (I in1, std::complex<R> const& in2) { |
---|
135 | return R(in1) / in2; |
---|
136 | } |
---|
137 | |
---|
138 | template<typename R, typename I> |
---|
139 | typename boost::enable_if< |
---|
140 | mpl::and_< |
---|
141 | boost::is_float<R>, |
---|
142 | boost::is_integral<I> |
---|
143 | >, |
---|
144 | std::complex<R> >::type inline operator/ (std::complex<R> const& in1, I in2) { |
---|
145 | return in1 / R (in2); |
---|
146 | } |
---|
147 | |
---|
148 | |
---|
149 | |
---|
150 | // Type traits - generic numeric properties and functions |
---|
151 | template<class T> |
---|
152 | struct type_traits; |
---|
153 | |
---|
154 | // Define properties for a generic scalar type |
---|
155 | template<class T> |
---|
156 | struct scalar_traits { |
---|
157 | typedef scalar_traits<T> self_type; |
---|
158 | typedef T value_type; |
---|
159 | typedef const T &const_reference; |
---|
160 | typedef T &reference; |
---|
161 | |
---|
162 | typedef T real_type; |
---|
163 | typedef real_type precision_type; // we do not know what type has more precision then the real_type |
---|
164 | |
---|
165 | static const unsigned plus_complexity = 1; |
---|
166 | static const unsigned multiplies_complexity = 1; |
---|
167 | |
---|
168 | static |
---|
169 | BOOST_UBLAS_INLINE |
---|
170 | real_type real (const_reference t) { |
---|
171 | return t; |
---|
172 | } |
---|
173 | static |
---|
174 | BOOST_UBLAS_INLINE |
---|
175 | real_type imag (const_reference /*t*/) { |
---|
176 | return 0; |
---|
177 | } |
---|
178 | static |
---|
179 | BOOST_UBLAS_INLINE |
---|
180 | value_type conj (const_reference t) { |
---|
181 | return t; |
---|
182 | } |
---|
183 | |
---|
184 | static |
---|
185 | BOOST_UBLAS_INLINE |
---|
186 | real_type type_abs (const_reference t) { |
---|
187 | return boost_numeric_ublas_abs (t); |
---|
188 | } |
---|
189 | static |
---|
190 | BOOST_UBLAS_INLINE |
---|
191 | value_type type_sqrt (const_reference t) { |
---|
192 | // force a type conversion back to value_type for intgral types |
---|
193 | return value_type (boost_numeric_ublas_sqrt (t)); |
---|
194 | } |
---|
195 | |
---|
196 | static |
---|
197 | BOOST_UBLAS_INLINE |
---|
198 | real_type norm_1 (const_reference t) { |
---|
199 | return self_type::type_abs (t); |
---|
200 | } |
---|
201 | static |
---|
202 | BOOST_UBLAS_INLINE |
---|
203 | real_type norm_2 (const_reference t) { |
---|
204 | return self_type::type_abs (t); |
---|
205 | } |
---|
206 | static |
---|
207 | BOOST_UBLAS_INLINE |
---|
208 | real_type norm_inf (const_reference t) { |
---|
209 | return self_type::type_abs (t); |
---|
210 | } |
---|
211 | |
---|
212 | static |
---|
213 | BOOST_UBLAS_INLINE |
---|
214 | bool equals (const_reference t1, const_reference t2) { |
---|
215 | return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON * |
---|
216 | (std::max) ((std::max) (self_type::norm_inf (t1), |
---|
217 | self_type::norm_inf (t2)), |
---|
218 | BOOST_UBLAS_TYPE_CHECK_MIN); |
---|
219 | } |
---|
220 | }; |
---|
221 | |
---|
222 | // Define default type traits, assume T is a scalar type |
---|
223 | template<class T> |
---|
224 | struct type_traits : scalar_traits <T> { |
---|
225 | typedef type_traits<T> self_type; |
---|
226 | typedef T value_type; |
---|
227 | typedef const T &const_reference; |
---|
228 | typedef T &reference; |
---|
229 | |
---|
230 | typedef T real_type; |
---|
231 | typedef real_type precision_type; |
---|
232 | static const unsigned multiplies_complexity = 1; |
---|
233 | |
---|
234 | }; |
---|
235 | |
---|
236 | // Define real type traits |
---|
237 | template<> |
---|
238 | struct type_traits<float> : scalar_traits<float> { |
---|
239 | typedef type_traits<float> self_type; |
---|
240 | typedef float value_type; |
---|
241 | typedef const value_type &const_reference; |
---|
242 | typedef value_type &reference; |
---|
243 | typedef value_type real_type; |
---|
244 | typedef double precision_type; |
---|
245 | }; |
---|
246 | template<> |
---|
247 | struct type_traits<double> : scalar_traits<double> { |
---|
248 | typedef type_traits<double> self_type; |
---|
249 | typedef double value_type; |
---|
250 | typedef const value_type &const_reference; |
---|
251 | typedef value_type &reference; |
---|
252 | typedef value_type real_type; |
---|
253 | typedef long double precision_type; |
---|
254 | }; |
---|
255 | template<> |
---|
256 | struct type_traits<long double> : scalar_traits<long double> { |
---|
257 | typedef type_traits<long double> self_type; |
---|
258 | typedef long double value_type; |
---|
259 | typedef const value_type &const_reference; |
---|
260 | typedef value_type &reference; |
---|
261 | typedef value_type real_type; |
---|
262 | typedef value_type precision_type; |
---|
263 | }; |
---|
264 | |
---|
265 | // Define properties for a generic complex type |
---|
266 | template<class T> |
---|
267 | struct complex_traits { |
---|
268 | typedef complex_traits<T> self_type; |
---|
269 | typedef T value_type; |
---|
270 | typedef const T &const_reference; |
---|
271 | typedef T &reference; |
---|
272 | |
---|
273 | typedef typename T::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 = 2; |
---|
277 | static const unsigned multiplies_complexity = 6; |
---|
278 | |
---|
279 | static |
---|
280 | BOOST_UBLAS_INLINE |
---|
281 | real_type real (const_reference t) { |
---|
282 | return std::real (t); |
---|
283 | } |
---|
284 | static |
---|
285 | BOOST_UBLAS_INLINE |
---|
286 | real_type imag (const_reference t) { |
---|
287 | return std::imag (t); |
---|
288 | } |
---|
289 | static |
---|
290 | BOOST_UBLAS_INLINE |
---|
291 | value_type conj (const_reference t) { |
---|
292 | return std::conj (t); |
---|
293 | } |
---|
294 | |
---|
295 | static |
---|
296 | BOOST_UBLAS_INLINE |
---|
297 | real_type type_abs (const_reference t) { |
---|
298 | return abs (t); |
---|
299 | } |
---|
300 | static |
---|
301 | BOOST_UBLAS_INLINE |
---|
302 | value_type type_sqrt (const_reference t) { |
---|
303 | return sqrt (t); |
---|
304 | } |
---|
305 | |
---|
306 | static |
---|
307 | BOOST_UBLAS_INLINE |
---|
308 | real_type norm_1 (const_reference t) { |
---|
309 | return self_type::type_abs (t); |
---|
310 | // original computation has been replaced because a complex number should behave like a scalar type |
---|
311 | // return type_traits<real_type>::type_abs (self_type::real (t)) + |
---|
312 | // type_traits<real_type>::type_abs (self_type::imag (t)); |
---|
313 | } |
---|
314 | static |
---|
315 | BOOST_UBLAS_INLINE |
---|
316 | real_type norm_2 (const_reference t) { |
---|
317 | return self_type::type_abs (t); |
---|
318 | } |
---|
319 | static |
---|
320 | BOOST_UBLAS_INLINE |
---|
321 | real_type norm_inf (const_reference t) { |
---|
322 | return self_type::type_abs (t); |
---|
323 | // original computation has been replaced because a complex number should behave like a scalar type |
---|
324 | // return (std::max) (type_traits<real_type>::type_abs (self_type::real (t)), |
---|
325 | // type_traits<real_type>::type_abs (self_type::imag (t))); |
---|
326 | } |
---|
327 | |
---|
328 | static |
---|
329 | BOOST_UBLAS_INLINE |
---|
330 | bool equals (const_reference t1, const_reference t2) { |
---|
331 | return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON * |
---|
332 | (std::max) ((std::max) (self_type::norm_inf (t1), |
---|
333 | self_type::norm_inf (t2)), |
---|
334 | BOOST_UBLAS_TYPE_CHECK_MIN); |
---|
335 | } |
---|
336 | }; |
---|
337 | |
---|
338 | // Define complex type traits |
---|
339 | template<> |
---|
340 | struct type_traits<std::complex<float> > : complex_traits<std::complex<float> >{ |
---|
341 | typedef type_traits<std::complex<float> > self_type; |
---|
342 | typedef std::complex<float> value_type; |
---|
343 | typedef const value_type &const_reference; |
---|
344 | typedef value_type &reference; |
---|
345 | typedef float real_type; |
---|
346 | typedef std::complex<double> precision_type; |
---|
347 | |
---|
348 | }; |
---|
349 | template<> |
---|
350 | struct type_traits<std::complex<double> > : complex_traits<std::complex<double> >{ |
---|
351 | typedef type_traits<std::complex<double> > self_type; |
---|
352 | typedef std::complex<double> value_type; |
---|
353 | typedef const value_type &const_reference; |
---|
354 | typedef value_type &reference; |
---|
355 | typedef double real_type; |
---|
356 | typedef std::complex<long double> precision_type; |
---|
357 | }; |
---|
358 | template<> |
---|
359 | struct type_traits<std::complex<long double> > : complex_traits<std::complex<long double> > { |
---|
360 | typedef type_traits<std::complex<long double> > self_type; |
---|
361 | typedef std::complex<long double> value_type; |
---|
362 | typedef const value_type &const_reference; |
---|
363 | typedef value_type &reference; |
---|
364 | typedef long double real_type; |
---|
365 | typedef value_type precision_type; |
---|
366 | }; |
---|
367 | |
---|
368 | #ifdef BOOST_UBLAS_USE_INTERVAL |
---|
369 | // Define scalar interval type traits |
---|
370 | template<> |
---|
371 | struct type_traits<boost::numeric::interval<float> > : scalar_traits<boost::numeric::interval<float> > { |
---|
372 | typedef type_traits<boost::numeric::interval<float> > self_type; |
---|
373 | typedef boost::numeric::interval<float> value_type; |
---|
374 | typedef const value_type &const_reference; |
---|
375 | typedef value_type &reference; |
---|
376 | typedef value_type real_type; |
---|
377 | typedef boost::numeric::interval<double> precision_type; |
---|
378 | |
---|
379 | }; |
---|
380 | template<> |
---|
381 | struct type_traits<boost::numeric::interval<double> > : scalar_traits<boost::numeric::interval<double> > { |
---|
382 | typedef type_traits<boost::numeric::interval<double> > self_type; |
---|
383 | typedef boost::numeric::interval<double> value_type; |
---|
384 | typedef const value_type &const_reference; |
---|
385 | typedef value_type &reference; |
---|
386 | typedef value_type real_type; |
---|
387 | typedef boost::numeric::interval<long double> precision_type; |
---|
388 | }; |
---|
389 | template<> |
---|
390 | struct type_traits<boost::numeric::interval<long double> > : scalar_traits<boost::numeric::interval<long double> > { |
---|
391 | typedef type_traits<boost::numeric::interval<long double> > self_type; |
---|
392 | typedef boost::numeric::interval<long double> value_type; |
---|
393 | typedef const value_type &const_reference; |
---|
394 | typedef value_type &reference; |
---|
395 | typedef value_type real_type; |
---|
396 | typedef value_type precision_type; |
---|
397 | }; |
---|
398 | #endif |
---|
399 | |
---|
400 | |
---|
401 | // Storage tags -- hierarchical definition of storage characteristics |
---|
402 | |
---|
403 | struct unknown_storage_tag {}; |
---|
404 | struct sparse_proxy_tag: public unknown_storage_tag {}; |
---|
405 | struct sparse_tag: public sparse_proxy_tag {}; |
---|
406 | struct packed_proxy_tag: public sparse_proxy_tag {}; |
---|
407 | struct packed_tag: public packed_proxy_tag {}; |
---|
408 | struct dense_proxy_tag: public packed_proxy_tag {}; |
---|
409 | struct dense_tag: public dense_proxy_tag {}; |
---|
410 | |
---|
411 | template<class S1, class S2> |
---|
412 | struct storage_restrict_traits { |
---|
413 | typedef S1 storage_category; |
---|
414 | }; |
---|
415 | |
---|
416 | template<> |
---|
417 | struct storage_restrict_traits<sparse_tag, dense_proxy_tag> { |
---|
418 | typedef sparse_proxy_tag storage_category; |
---|
419 | }; |
---|
420 | template<> |
---|
421 | struct storage_restrict_traits<sparse_tag, packed_proxy_tag> { |
---|
422 | typedef sparse_proxy_tag storage_category; |
---|
423 | }; |
---|
424 | template<> |
---|
425 | struct storage_restrict_traits<sparse_tag, sparse_proxy_tag> { |
---|
426 | typedef sparse_proxy_tag storage_category; |
---|
427 | }; |
---|
428 | |
---|
429 | template<> |
---|
430 | struct storage_restrict_traits<packed_tag, dense_proxy_tag> { |
---|
431 | typedef packed_proxy_tag storage_category; |
---|
432 | }; |
---|
433 | template<> |
---|
434 | struct storage_restrict_traits<packed_tag, packed_proxy_tag> { |
---|
435 | typedef packed_proxy_tag storage_category; |
---|
436 | }; |
---|
437 | template<> |
---|
438 | struct storage_restrict_traits<packed_tag, sparse_proxy_tag> { |
---|
439 | typedef sparse_proxy_tag storage_category; |
---|
440 | }; |
---|
441 | |
---|
442 | template<> |
---|
443 | struct storage_restrict_traits<packed_proxy_tag, sparse_proxy_tag> { |
---|
444 | typedef sparse_proxy_tag storage_category; |
---|
445 | }; |
---|
446 | |
---|
447 | template<> |
---|
448 | struct storage_restrict_traits<dense_tag, dense_proxy_tag> { |
---|
449 | typedef dense_proxy_tag storage_category; |
---|
450 | }; |
---|
451 | template<> |
---|
452 | struct storage_restrict_traits<dense_tag, packed_proxy_tag> { |
---|
453 | typedef packed_proxy_tag storage_category; |
---|
454 | }; |
---|
455 | template<> |
---|
456 | struct storage_restrict_traits<dense_tag, sparse_proxy_tag> { |
---|
457 | typedef sparse_proxy_tag storage_category; |
---|
458 | }; |
---|
459 | |
---|
460 | template<> |
---|
461 | struct storage_restrict_traits<dense_proxy_tag, packed_proxy_tag> { |
---|
462 | typedef packed_proxy_tag storage_category; |
---|
463 | }; |
---|
464 | template<> |
---|
465 | struct storage_restrict_traits<dense_proxy_tag, sparse_proxy_tag> { |
---|
466 | typedef sparse_proxy_tag storage_category; |
---|
467 | }; |
---|
468 | |
---|
469 | |
---|
470 | // Iterator tags -- hierarchical definition of storage characteristics |
---|
471 | |
---|
472 | struct sparse_bidirectional_iterator_tag : public std::bidirectional_iterator_tag {}; |
---|
473 | struct packed_random_access_iterator_tag : public std::random_access_iterator_tag {}; |
---|
474 | struct dense_random_access_iterator_tag : public packed_random_access_iterator_tag {}; |
---|
475 | |
---|
476 | // Thanks to Kresimir Fresl for convincing Comeau with iterator_base_traits ;-) |
---|
477 | template<class IC> |
---|
478 | struct iterator_base_traits {}; |
---|
479 | |
---|
480 | template<> |
---|
481 | struct iterator_base_traits<std::forward_iterator_tag> { |
---|
482 | template<class I, class T> |
---|
483 | struct iterator_base { |
---|
484 | typedef forward_iterator_base<std::forward_iterator_tag, I, T> type; |
---|
485 | }; |
---|
486 | }; |
---|
487 | |
---|
488 | template<> |
---|
489 | struct iterator_base_traits<std::bidirectional_iterator_tag> { |
---|
490 | template<class I, class T> |
---|
491 | struct iterator_base { |
---|
492 | typedef bidirectional_iterator_base<std::bidirectional_iterator_tag, I, T> type; |
---|
493 | }; |
---|
494 | }; |
---|
495 | template<> |
---|
496 | struct iterator_base_traits<sparse_bidirectional_iterator_tag> { |
---|
497 | template<class I, class T> |
---|
498 | struct iterator_base { |
---|
499 | typedef bidirectional_iterator_base<sparse_bidirectional_iterator_tag, I, T> type; |
---|
500 | }; |
---|
501 | }; |
---|
502 | |
---|
503 | template<> |
---|
504 | struct iterator_base_traits<std::random_access_iterator_tag> { |
---|
505 | template<class I, class T> |
---|
506 | struct iterator_base { |
---|
507 | typedef random_access_iterator_base<std::random_access_iterator_tag, I, T> type; |
---|
508 | }; |
---|
509 | }; |
---|
510 | template<> |
---|
511 | struct iterator_base_traits<packed_random_access_iterator_tag> { |
---|
512 | template<class I, class T> |
---|
513 | struct iterator_base { |
---|
514 | typedef random_access_iterator_base<packed_random_access_iterator_tag, I, T> type; |
---|
515 | }; |
---|
516 | }; |
---|
517 | template<> |
---|
518 | struct iterator_base_traits<dense_random_access_iterator_tag> { |
---|
519 | template<class I, class T> |
---|
520 | struct iterator_base { |
---|
521 | typedef random_access_iterator_base<dense_random_access_iterator_tag, I, T> type; |
---|
522 | }; |
---|
523 | }; |
---|
524 | |
---|
525 | template<class I1, class I2> |
---|
526 | struct iterator_restrict_traits { |
---|
527 | typedef I1 iterator_category; |
---|
528 | }; |
---|
529 | |
---|
530 | template<> |
---|
531 | struct iterator_restrict_traits<packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag> { |
---|
532 | typedef sparse_bidirectional_iterator_tag iterator_category; |
---|
533 | }; |
---|
534 | template<> |
---|
535 | struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag> { |
---|
536 | typedef sparse_bidirectional_iterator_tag iterator_category; |
---|
537 | }; |
---|
538 | |
---|
539 | template<> |
---|
540 | struct iterator_restrict_traits<dense_random_access_iterator_tag, sparse_bidirectional_iterator_tag> { |
---|
541 | typedef sparse_bidirectional_iterator_tag iterator_category; |
---|
542 | }; |
---|
543 | template<> |
---|
544 | struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, dense_random_access_iterator_tag> { |
---|
545 | typedef sparse_bidirectional_iterator_tag iterator_category; |
---|
546 | }; |
---|
547 | |
---|
548 | template<> |
---|
549 | struct iterator_restrict_traits<dense_random_access_iterator_tag, packed_random_access_iterator_tag> { |
---|
550 | typedef packed_random_access_iterator_tag iterator_category; |
---|
551 | }; |
---|
552 | template<> |
---|
553 | struct iterator_restrict_traits<packed_random_access_iterator_tag, dense_random_access_iterator_tag> { |
---|
554 | typedef packed_random_access_iterator_tag iterator_category; |
---|
555 | }; |
---|
556 | |
---|
557 | template<class I> |
---|
558 | BOOST_UBLAS_INLINE |
---|
559 | void increment (I &it, const I &it_end, typename I::difference_type compare, packed_random_access_iterator_tag) { |
---|
560 | it += (std::min) (compare, it_end - it); |
---|
561 | } |
---|
562 | template<class I> |
---|
563 | BOOST_UBLAS_INLINE |
---|
564 | void increment (I &it, const I &/* it_end */, typename I::difference_type /* compare */, sparse_bidirectional_iterator_tag) { |
---|
565 | ++ it; |
---|
566 | } |
---|
567 | template<class I> |
---|
568 | BOOST_UBLAS_INLINE |
---|
569 | void increment (I &it, const I &it_end, typename I::difference_type compare) { |
---|
570 | increment (it, it_end, compare, typename I::iterator_category ()); |
---|
571 | } |
---|
572 | |
---|
573 | template<class I> |
---|
574 | BOOST_UBLAS_INLINE |
---|
575 | void increment (I &it, const I &it_end) { |
---|
576 | #if BOOST_UBLAS_TYPE_CHECK |
---|
577 | I cit (it); |
---|
578 | while (cit != it_end) { |
---|
579 | BOOST_UBLAS_CHECK (*cit == typename I::value_type/*zero*/(), internal_logic ()); |
---|
580 | ++ cit; |
---|
581 | } |
---|
582 | #endif |
---|
583 | it = it_end; |
---|
584 | } |
---|
585 | |
---|
586 | namespace detail { |
---|
587 | |
---|
588 | // specialisation which define whether a type has a trivial constructor |
---|
589 | // or not. This is used by array types. |
---|
590 | template<typename T> |
---|
591 | struct has_trivial_constructor : public boost::has_trivial_constructor<T> {}; |
---|
592 | |
---|
593 | template<typename T> |
---|
594 | struct has_trivial_destructor : public boost::has_trivial_destructor<T> {}; |
---|
595 | |
---|
596 | template<typename FLT> |
---|
597 | struct has_trivial_constructor<std::complex<FLT> > : public boost::true_type {}; |
---|
598 | |
---|
599 | template<typename FLT> |
---|
600 | struct has_trivial_destructor<std::complex<FLT> > : public boost::true_type {}; |
---|
601 | |
---|
602 | } |
---|
603 | |
---|
604 | |
---|
605 | /** \brief Traits class to extract type information from a constant matrix or vector CONTAINER. |
---|
606 | * |
---|
607 | */ |
---|
608 | template < class E > |
---|
609 | struct container_view_traits { |
---|
610 | /// type of indices |
---|
611 | typedef typename E::size_type size_type; |
---|
612 | /// type of differences of indices |
---|
613 | typedef typename E::difference_type difference_type; |
---|
614 | |
---|
615 | /// storage category: \c unknown_storage_tag, \c dense_tag, \c packed_tag, ... |
---|
616 | typedef typename E::storage_category storage_category; |
---|
617 | |
---|
618 | /// type of elements |
---|
619 | typedef typename E::value_type value_type; |
---|
620 | /// const reference to an element |
---|
621 | typedef typename E::const_reference const_reference; |
---|
622 | |
---|
623 | /// type used in expressions to mark a reference to this class (usually a const container_reference<const E> or the class itself) |
---|
624 | typedef typename E::const_closure_type const_closure_type; |
---|
625 | }; |
---|
626 | |
---|
627 | /** \brief Traits class to extract additional type information from a mutable matrix or vector CONTAINER. |
---|
628 | * |
---|
629 | */ |
---|
630 | template < class E > |
---|
631 | struct mutable_container_traits { |
---|
632 | /// reference to an element |
---|
633 | typedef typename E::reference reference; |
---|
634 | |
---|
635 | /// type used in expressions to mark a reference to this class (usually a container_reference<E> or the class itself) |
---|
636 | typedef typename E::closure_type closure_type; |
---|
637 | }; |
---|
638 | |
---|
639 | /** \brief Traits class to extract type information from a matrix or vector CONTAINER. |
---|
640 | * |
---|
641 | */ |
---|
642 | template < class E > |
---|
643 | struct container_traits |
---|
644 | : container_view_traits<E>, mutable_container_traits<E> { |
---|
645 | |
---|
646 | }; |
---|
647 | |
---|
648 | |
---|
649 | /** \brief Traits class to extract type information from a constant MATRIX. |
---|
650 | * |
---|
651 | */ |
---|
652 | template < class MATRIX > |
---|
653 | struct matrix_view_traits : container_view_traits <MATRIX> { |
---|
654 | |
---|
655 | /// orientation of the matrix, either \c row_major_tag, \c column_major_tag or \c unknown_orientation_tag |
---|
656 | typedef typename MATRIX::orientation_category orientation_category; |
---|
657 | |
---|
658 | /// row iterator for the matrix |
---|
659 | typedef typename MATRIX::const_iterator1 const_iterator1; |
---|
660 | |
---|
661 | /// column iterator for the matrix |
---|
662 | typedef typename MATRIX::const_iterator2 const_iterator2; |
---|
663 | }; |
---|
664 | |
---|
665 | /** \brief Traits class to extract additional type information from a mutable MATRIX. |
---|
666 | * |
---|
667 | */ |
---|
668 | template < class MATRIX > |
---|
669 | struct mutable_matrix_traits |
---|
670 | : mutable_container_traits <MATRIX> { |
---|
671 | |
---|
672 | /// row iterator for the matrix |
---|
673 | typedef typename MATRIX::iterator1 iterator1; |
---|
674 | |
---|
675 | /// column iterator for the matrix |
---|
676 | typedef typename MATRIX::iterator2 iterator2; |
---|
677 | }; |
---|
678 | |
---|
679 | |
---|
680 | /** \brief Traits class to extract type information from a MATRIX. |
---|
681 | * |
---|
682 | */ |
---|
683 | template < class MATRIX > |
---|
684 | struct matrix_traits |
---|
685 | : matrix_view_traits <MATRIX>, mutable_matrix_traits <MATRIX> { |
---|
686 | }; |
---|
687 | |
---|
688 | /** \brief Traits class to extract type information from a VECTOR. |
---|
689 | * |
---|
690 | */ |
---|
691 | template < class VECTOR > |
---|
692 | struct vector_view_traits : container_view_traits <VECTOR> { |
---|
693 | |
---|
694 | /// iterator for the VECTOR |
---|
695 | typedef typename VECTOR::const_iterator const_iterator; |
---|
696 | |
---|
697 | /// iterator pointing to the first element |
---|
698 | static |
---|
699 | const_iterator begin(const VECTOR & v) { |
---|
700 | return v.begin(); |
---|
701 | } |
---|
702 | /// iterator pointing behind the last element |
---|
703 | static |
---|
704 | const_iterator end(const VECTOR & v) { |
---|
705 | return v.end(); |
---|
706 | } |
---|
707 | |
---|
708 | }; |
---|
709 | |
---|
710 | /** \brief Traits class to extract type information from a VECTOR. |
---|
711 | * |
---|
712 | */ |
---|
713 | template < class VECTOR > |
---|
714 | struct mutable_vector_traits : mutable_container_traits <VECTOR> { |
---|
715 | /// iterator for the VECTOR |
---|
716 | typedef typename VECTOR::iterator iterator; |
---|
717 | |
---|
718 | /// iterator pointing to the first element |
---|
719 | static |
---|
720 | iterator begin(VECTOR & v) { |
---|
721 | return v.begin(); |
---|
722 | } |
---|
723 | |
---|
724 | /// iterator pointing behind the last element |
---|
725 | static |
---|
726 | iterator end(VECTOR & v) { |
---|
727 | return v.end(); |
---|
728 | } |
---|
729 | }; |
---|
730 | |
---|
731 | /** \brief Traits class to extract type information from a VECTOR. |
---|
732 | * |
---|
733 | */ |
---|
734 | template < class VECTOR > |
---|
735 | struct vector_traits |
---|
736 | : vector_view_traits <VECTOR>, mutable_vector_traits <VECTOR> { |
---|
737 | }; |
---|
738 | |
---|
739 | |
---|
740 | // Note: specializations for T[N] and T[M][N] have been moved to traits/c_array.hpp |
---|
741 | |
---|
742 | }}} |
---|
743 | |
---|
744 | #endif |
---|