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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
| | Fix FTBFS on i686-linux due to rounding issue (see references).
Fixes Guix bug #22049 (see below).
Copied from Debian.
Source:
https://sources.debian.net/src/ilmbase/2.2.0-11/debian/patches/testBoxAlgo.patch/
References:
https://lists.nongnu.org/archive/html/openexr-devel/2015-12/msg00001.html
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22049
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=815712
https://anonscm.debian.org/cgit/pkg-phototools/ilmbase.git/commit/?id=ab28bb45cdad8adc32e345b777ab8e692b1d9a9c
---
Subject: testBox: allow fuzzy comparison of floats, doubles
From: Steven Chamberlain <steven@pyro.eu.org>
Date: Wed, 24 Feb 2016 01:10:11 +0000
Allow for inexact values, as long as the error is smaller than the
epsilon of the data type.
On 32-bit x86, allow even greater discrepency at double
precision, due to possible double-rounding. See
https://lists.nongnu.org/archive/html/openexr-devel/2015-12/msg00001.html
Index: ilmbase/ImathTest/testBox.cpp
===================================================================
--- ilmbase.orig/ImathTest/testBox.cpp
+++ ilmbase/ImathTest/testBox.cpp
@@ -47,6 +47,58 @@ using namespace IMATH_INTERNAL_NAMESPACE
namespace {
+template <class T>
+bool
+approximatelyEqual (const T &p1, const T &p2)
+{
+ /* int and short should be exact */
+ return (p1 == p2);
+}
+
+bool
+approximatelyEqual (const Vec2<float> &p1, const Vec2<float> &p2)
+{
+ float e = limits<float>::epsilon();
+ float m = 0;
+
+ for (int i = 0; i < 2; ++i)
+ {
+ m = max (m, abs (p1[i]));
+ m = max (m, abs (p2[i]));
+ }
+
+ for (int i = 0; i < 2; ++i)
+ if (!equalWithAbsError (p1[i], p2[i], m * e))
+ return false;
+
+ return true;
+}
+
+bool
+approximatelyEqual (const Vec2<double> &p1, const Vec2<double> &p2)
+{
+#if defined(__i386__) || defined(_M_IX86)
+ /* double-rounding on 32-bit x86 may cause larger error:
+ use epsilon of float rather than double */
+ double e = limits<float>::epsilon();
+#else
+ double e = limits<double>::epsilon();
+#endif
+ double m = 0;
+
+ for (int i = 0; i < 2; ++i)
+ {
+ m = max (m, abs (p1[i]));
+ m = max (m, abs (p2[i]));
+ }
+
+ for (int i = 0; i < 2; ++i)
+ if (!equalWithAbsError (p1[i], p2[i], m * e))
+ return false;
+
+ return true;
+}
+
//
// Test case generation utility - create a vector of IMATH_INTERNAL_NAMESPACE::Vec{2,3,4}
// with all permutations of integers 1..T::dimensions().
@@ -250,7 +302,8 @@ testExtendByPoint(const char *type)
IMATH_INTERNAL_NAMESPACE::Box<T> b;
b.extendBy(p);
- assert(b.min == p && b.max == p);
+ assert (approximatelyEqual (b.min, p));
+ assert (approximatelyEqual (b.max, p));
}
//
@@ -283,7 +336,8 @@ testExtendByPoint(const char *type)
b.extendBy(p);
- assert(b.min == min && b.max == max);
+ assert (approximatelyEqual (b.min, min));
+ assert (approximatelyEqual (b.max, max));
}
}
}
@@ -358,7 +412,8 @@ testExtendByBox(const char *type)
}
b.extendBy(IMATH_INTERNAL_NAMESPACE::Box<T>(p0, p1));
- assert(b.min == min && b.max == max);
+ assert (approximatelyEqual (b.min, min));
+ assert (approximatelyEqual (b.max, max));
}
}
}
|