det.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /* Boost test/det.cpp
  2. * test protected and unprotected rounding on an unstable determinant
  3. *
  4. * Copyright 2002-2003 Guillaume Melquiond
  5. *
  6. * Distributed under the Boost Software License, Version 1.0.
  7. * (See accompanying file LICENSE_1_0.txt or
  8. * copy at http://www.boost.org/LICENSE_1_0.txt)
  9. */
  10. #include <boost/numeric/interval.hpp>
  11. #include <boost/test/minimal.hpp>
  12. #include "bugs.hpp"
  13. #define size 8
  14. template<class I>
  15. void det(I (&mat)[size][size]) {
  16. for(int i = 0; i < size; i++)
  17. for(int j = 0; j < size; j++)
  18. mat[i][j] = I(1) / I(i + j + 1);
  19. for(int i = 0; i < size - 1; i++) {
  20. int m = i, n = i;
  21. typename I::base_type v = 0;
  22. for(int a = i; a < size; a++)
  23. for(int b = i; b < size; b++) {
  24. typename I::base_type w = abs(mat[a][b]).lower();
  25. if (w > v) { m = a; n = b; v = w; }
  26. }
  27. if (n != i)
  28. for(int a = 0; a < size; a++) {
  29. I t = mat[a][n];
  30. mat[a][n] = mat[a][i];
  31. mat[a][i] = t;
  32. }
  33. if (m != i)
  34. for(int b = i; b < size; b++) {
  35. I t = mat[m][b];
  36. mat[m][b] = mat[m][i];
  37. mat[m][i] = t;
  38. }
  39. if (((m + n) & 1) == 1) { };
  40. I c = mat[i][i];
  41. for(int j = i + 1; j < size; j++) {
  42. I f = mat[j][i] / c;
  43. for(int k = i; k < size; k++)
  44. mat[j][k] -= f * mat[i][k];
  45. }
  46. if (zero_in(c)) return;
  47. }
  48. }
  49. namespace my_namespace {
  50. using namespace boost;
  51. using namespace numeric;
  52. using namespace interval_lib;
  53. template<class T>
  54. struct variants {
  55. typedef interval<T> I_op;
  56. typedef typename change_rounding<I_op, save_state<rounded_arith_std<T> > >::type I_sp;
  57. typedef typename unprotect<I_op>::type I_ou;
  58. typedef typename unprotect<I_sp>::type I_su;
  59. typedef T type;
  60. };
  61. }
  62. template<class T>
  63. bool test() {
  64. typedef my_namespace::variants<double> types;
  65. types::I_op mat_op[size][size];
  66. types::I_sp mat_sp[size][size];
  67. types::I_ou mat_ou[size][size];
  68. types::I_su mat_su[size][size];
  69. det(mat_op);
  70. det(mat_sp);
  71. { types::I_op::traits_type::rounding rnd; det(mat_ou); }
  72. { types::I_sp::traits_type::rounding rnd; det(mat_su); }
  73. for(int i = 0; i < size; i++)
  74. for(int j = 0; j < size; j++) {
  75. typedef types::I_op I;
  76. I d_op = mat_op[i][j];
  77. I d_sp = mat_sp[i][j];
  78. I d_ou = mat_ou[i][j];
  79. I d_su = mat_su[i][j];
  80. if (!(equal(d_op, d_sp) && equal(d_sp, d_ou) && equal(d_ou, d_su)))
  81. return false;
  82. }
  83. return true;
  84. }
  85. int test_main(int, char *[]) {
  86. BOOST_CHECK(test<float>());
  87. BOOST_CHECK(test<double>());
  88. BOOST_CHECK(test<long double>());
  89. # ifdef __BORLANDC__
  90. ::detail::ignore_warnings();
  91. # endif
  92. return 0;
  93. }