File: rounding_modes2.cpp

package info (click to toggle)
cgal 4.0-5
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 65,068 kB
  • sloc: cpp: 500,870; ansic: 102,544; sh: 321; python: 92; makefile: 75; xml: 2
file content (95 lines) | stat: -rw-r--r-- 2,825 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// This tests the rounding mode functions.

#include <CGAL/basic.h>
#include <CGAL/Interval_nt.h>
#include <iostream>

typedef CGAL::Interval_nt_advanced NT_adv;
typedef CGAL::Interval_nt<>        NT;

void print_res (bool res)
{ std::cout << (res ? "ok" : "ERROR") << std::endl; }

// The results of 1-epsilon and -1+epsilon are enough
// to detect exactly the current rounding mode.
//                          1-MIN_DOUBLE
//                        +------+-------+
//                        |  1   | 1-ulp |
//               +--------+------+-------+
// -1+MIN_DOUBLE | -1     | near |  -inf |
//               | -1+ulp | +inf |  zero |
//               +--------+------+-------+

// I use a global variable here to avoid constant propagation.
double IA_min_double;

CGAL::FPU_CW_t
FPU_empiric_test()
{
    IA_min_double = CGAL_IA_STOP_CPROP(CGAL_IA_MIN_DOUBLE);
    double y = 1.0, z = -1.0;
    double ye, ze;
    ye = y - IA_min_double;
    ze = z + IA_min_double;
    if (y == ye && z == ze) return CGAL_FE_TONEAREST;
    if (y == ye) return CGAL_FE_UPWARD;
    if (z == ze) return CGAL_FE_DOWNWARD;
    return CGAL_FE_TOWARDZERO;
}

void print_rounding_name (CGAL::FPU_CW_t r)
{
  switch (r) {
  case CGAL_FE_TONEAREST:  std::cout << "NEAR\n"; break;
  case CGAL_FE_DOWNWARD:   std::cout << "DOWN\n"; break;
  case CGAL_FE_UPWARD:     std::cout << "UP\n"; break;
  case CGAL_FE_TOWARDZERO: std::cout << "ZERO\n"; break;
  default:                 std::cout << "unknown !\n";
  }
}

int main()
{
   bool flag = true;

   flag = flag && (FPU_empiric_test() == CGAL_FE_TONEAREST);
   std::cout << "default: ";
   print_res(flag);

   // Should be a no-op.
   CGAL::FPU_set_cw(CGAL::FPU_get_cw());
   flag = flag && (FPU_empiric_test() == CGAL_FE_TONEAREST);
   std::cout << "get/set: ";
   print_res(flag);
   if (!flag) print_rounding_name(FPU_empiric_test());

   // Rounding to zero.
   CGAL::FPU_set_cw(CGAL_FE_TOWARDZERO);
   flag = flag && (FPU_empiric_test() == CGAL_FE_TOWARDZERO);
   std::cout << "zero   : ";
   print_res(flag);
   if (!flag) print_rounding_name(FPU_empiric_test());

   // Rounding to infinity.
   CGAL::FPU_set_cw(CGAL_FE_UPWARD);
   flag = flag && (FPU_empiric_test() == CGAL_FE_UPWARD);
   std::cout << "+inf   : ";
   print_res(flag);
   if (!flag) print_rounding_name(FPU_empiric_test());

   // Rounding to minus infinity.
   CGAL::FPU_set_cw(CGAL_FE_DOWNWARD);
   flag = flag && (FPU_empiric_test() == CGAL_FE_DOWNWARD);
   std::cout << "-inf   : ";
   print_res(flag);
   if (!flag) print_rounding_name(FPU_empiric_test());

   // Rounding to nearest.
   CGAL::FPU_set_cw(CGAL_FE_TONEAREST);
   flag = flag && (FPU_empiric_test() == CGAL_FE_TONEAREST);
   std::cout << "near   : ";
   print_res(flag);
   if (!flag) print_rounding_name(FPU_empiric_test());

   return (int) !flag;
}