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 29 namespace 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 realboost::numeric::ublas::scalar_traits72 real_type real (const_reference t) { 73 return t; 74 } 75 static 76 BOOST_UBLAS_INLINE imagboost::numeric::ublas::scalar_traits77 real_type imag (const_reference /*t*/) { 78 return 0; 79 } 80 static 81 BOOST_UBLAS_INLINE conjboost::numeric::ublas::scalar_traits82 value_type conj (const_reference t) { 83 return t; 84 } 85 86 static 87 BOOST_UBLAS_INLINE absboost::numeric::ublas::scalar_traits88 real_type abs (const_reference t) { 89 return std::abs (t); 90 } 91 static 92 BOOST_UBLAS_INLINE sqrtboost::numeric::ublas::scalar_traits93 value_type sqrt (const_reference t) { 94 return std::sqrt (t); 95 } 96 97 static 98 BOOST_UBLAS_INLINE norm_1boost::numeric::ublas::scalar_traits99 real_type norm_1 (const_reference t) { 100 return self_type::abs (t); 101 } 102 static 103 BOOST_UBLAS_INLINE norm_2boost::numeric::ublas::scalar_traits104 real_type norm_2 (const_reference t) { 105 return self_type::abs (t); 106 } 107 static 108 BOOST_UBLAS_INLINE norm_infboost::numeric::ublas::scalar_traits109 real_type norm_inf (const_reference t) { 110 return self_type::abs (t); 111 } 112 113 static 114 BOOST_UBLAS_INLINE equalsboost::numeric::ublas::scalar_traits115 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 realboost::numeric::ublas::complex_traits182 real_type real (const_reference t) { 183 return std::real (t); 184 } 185 static 186 BOOST_UBLAS_INLINE imagboost::numeric::ublas::complex_traits187 real_type imag (const_reference t) { 188 return std::imag (t); 189 } 190 static 191 BOOST_UBLAS_INLINE conjboost::numeric::ublas::complex_traits192 value_type conj (const_reference t) { 193 return std::conj (t); 194 } 195 196 static 197 BOOST_UBLAS_INLINE absboost::numeric::ublas::complex_traits198 real_type abs (const_reference t) { 199 return std::abs (t); 200 } 201 static 202 BOOST_UBLAS_INLINE sqrtboost::numeric::ublas::complex_traits203 value_type sqrt (const_reference t) { 204 return std::sqrt (t); 205 } 206 207 static 208 BOOST_UBLAS_INLINE norm_1boost::numeric::ublas::complex_traits209 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 norm_2boost::numeric::ublas::complex_traits215 real_type norm_2 (const_reference t) { 216 return self_type::abs (t); 217 } 218 static 219 BOOST_UBLAS_INLINE norm_infboost::numeric::ublas::complex_traits220 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 equalsboost::numeric::ublas::complex_traits227 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 absboost::numeric::ublas::scalar_interval_type_traits281 real_type abs (const_reference t) { 282 return boost::numeric::abs (t); 283 } 284 static 285 BOOST_UBLAS_INLINE sqrtboost::numeric::ublas::scalar_interval_type_traits286 value_type sqrt (const_reference t) { 287 return boost::numeric::sqrt (t); 288 } 289 290 static 291 BOOST_UBLAS_INLINE norm_1boost::numeric::ublas::scalar_interval_type_traits292 real_type norm_1 (const_reference t) { 293 return self_type::abs (t); 294 } 295 static 296 BOOST_UBLAS_INLINE norm_2boost::numeric::ublas::scalar_interval_type_traits297 real_type norm_2 (const_reference t) { 298 return self_type::abs (t); 299 } 300 static 301 BOOST_UBLAS_INLINE norm_infboost::numeric::ublas::scalar_interval_type_traits302 real_type norm_inf (const_reference t) { 303 return self_type::abs (t); 304 } 305 306 static 307 BOOST_UBLAS_INLINE equalsboost::numeric::ublas::scalar_interval_type_traits308 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 increment(I & it,const I & it_end,typename I::difference_type compare,packed_random_access_iterator_tag)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 increment(I & it,const I &,typename I::difference_type,sparse_bidirectional_iterator_tag)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 increment(I & it,const I & it_end,typename I::difference_type compare)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 increment(I & it,const I & it_end)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 537