Skip to content

Commit 994d042

Browse files
committed
WIP: fixing precision bugs
1 parent 1f7c38b commit 994d042

File tree

14 files changed

+1308
-158
lines changed

14 files changed

+1308
-158
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// adaptive_threshold.cpp: debug adaptive threshold with ereal arithmetic
2+
#include <universal/utility/directives.hpp>
3+
#include <universal/number/ereal/ereal.hpp>
4+
#include <universal/verification/test_suite.hpp>
5+
#include <universal/verification/test_suite_mathlib_adaptive.hpp>
6+
7+
int main() {
8+
using namespace sw::universal;
9+
using Real = ereal<16>;
10+
11+
std::cout << "Debug: ereal arithmetic in check_relative_error\n";
12+
std::cout << "================================================\n\n";
13+
14+
Real x(1.0);
15+
Real y(1.0 + 1e-20);
16+
17+
std::cout << "x = " << x << "\n";
18+
std::cout << "y = " << y << "\n";
19+
20+
Real diff = y - x;
21+
std::cout << "y - x = " << diff << "\n";
22+
23+
Real abs_diff = abs(diff);
24+
std::cout << "abs(y - x) = " << abs_diff << "\n";
25+
26+
Real rel_error = abs_diff / abs(y);
27+
std::cout << "rel_error = abs(y-x) / abs(y) = " << rel_error << "\n";
28+
std::cout << "rel_error as double = " << double(rel_error) << "\n";
29+
30+
double threshold = get_adaptive_threshold<Real>();
31+
std::cout << "threshold = " << threshold << "\n";
32+
33+
bool passes = double(rel_error) < threshold;
34+
std::cout << "Passes check? " << (passes ? "YES" : "NO") << "\n";
35+
36+
std::cout << "\n--- Testing distant values ---\n";
37+
Real z(100.0);
38+
std::cout << "x = " << x << "\n";
39+
std::cout << "z = " << z << "\n";
40+
41+
Real diff2 = x - z;
42+
std::cout << "x - z = " << diff2 << "\n";
43+
44+
Real abs_diff2 = abs(diff2);
45+
std::cout << "abs(x - z) = " << abs_diff2 << "\n";
46+
47+
Real rel_error2 = abs_diff2 / abs(z);
48+
std::cout << "rel_error2 = abs(x-z) / abs(z) = " << rel_error2 << "\n";
49+
std::cout << "rel_error2 as double = " << double(rel_error2) << "\n";
50+
51+
bool passes2 = double(rel_error2) < threshold;
52+
std::cout << "Passes check? " << (passes2 ? "YES (WRONG!)" : "NO (correct)") << "\n";
53+
54+
return 0;
55+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// adaptive_simple.cpp: simple validation of adaptive threshold utilities
2+
//
3+
// Copyright (C) 2017 Stillwater Supercomputing, Inc.
4+
// SPDX-License-Identifier: MIT
5+
//
6+
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
7+
#include <universal/utility/directives.hpp>
8+
#include <universal/number/ereal/ereal.hpp>
9+
#include <universal/verification/test_suite.hpp>
10+
#include <universal/verification/test_suite_mathlib_adaptive.hpp>
11+
12+
int main()
13+
try {
14+
using namespace sw::universal;
15+
16+
std::cout << "Adaptive Threshold Utilities - Simple Validation\n";
17+
std::cout << "=================================================\n\n";
18+
19+
int nrOfFailedTestCases = 0;
20+
21+
// Test different precision levels
22+
std::cout << "Precision and Threshold Scaling:\n";
23+
std::cout << "--------------------------------\n";
24+
25+
double threshold_f = get_adaptive_threshold<float>();
26+
std::cout << "float (digits10=" << std::numeric_limits<float>::digits10
27+
<< "): threshold = " << threshold_f << "\n";
28+
29+
double threshold_d = get_adaptive_threshold<double>();
30+
std::cout << "double (digits10=" << std::numeric_limits<double>::digits10
31+
<< "): threshold = " << threshold_d << "\n";
32+
33+
using Real8 = ereal<8>;
34+
double threshold_e8 = get_adaptive_threshold<Real8>();
35+
std::cout << "ereal<8> (digits10=" << std::numeric_limits<Real8>::digits10
36+
<< "): threshold = " << threshold_e8 << "\n";
37+
38+
using Real12 = ereal<12>;
39+
double threshold_e12 = get_adaptive_threshold<Real12>();
40+
std::cout << "ereal<12> (digits10=" << std::numeric_limits<Real12>::digits10
41+
<< "): threshold = " << threshold_e12 << "\n";
42+
43+
using Real16 = ereal<16>;
44+
double threshold_e16 = get_adaptive_threshold<Real16>();
45+
std::cout << "ereal<16> (digits10=" << std::numeric_limits<Real16>::digits10
46+
<< "): threshold = " << threshold_e16 << "\n";
47+
48+
using Real19 = ereal<19>;
49+
double threshold_e19 = get_adaptive_threshold<Real19>();
50+
std::cout << "ereal<19> (digits10=" << std::numeric_limits<Real19>::digits10
51+
<< "): threshold = " << threshold_e19 << " (maximum valid)\n";
52+
53+
// Verify thresholds scale properly
54+
std::cout << "\nThreshold Validation:\n";
55+
if (threshold_e19 < threshold_e16) {
56+
std::cout << "✓ PASS: ereal<19> has tighter threshold than ereal<16>\n";
57+
} else {
58+
std::cerr << "✗ FAIL: Threshold scaling incorrect\n";
59+
++nrOfFailedTestCases;
60+
}
61+
62+
if (threshold_e16 < threshold_e12) {
63+
std::cout << "✓ PASS: ereal<16> has tighter threshold than ereal<12>\n";
64+
} else {
65+
std::cerr << "✗ FAIL: Threshold scaling incorrect\n";
66+
++nrOfFailedTestCases;
67+
}
68+
69+
if (threshold_e12 < threshold_e8) {
70+
std::cout << "✓ PASS: ereal<12> has tighter threshold than ereal<8>\n";
71+
} else {
72+
std::cerr << "✗ FAIL: Threshold scaling incorrect\n";
73+
++nrOfFailedTestCases;
74+
}
75+
76+
if (threshold_e16 < threshold_d) {
77+
std::cout << "✓ PASS: ereal<16> has tighter threshold than double\n";
78+
} else {
79+
std::cerr << "✗ FAIL: ereal<16> threshold should be tighter than double\n";
80+
++nrOfFailedTestCases;
81+
}
82+
83+
// Test exact value checking
84+
std::cout << "\nExact Value Checking:\n";
85+
Real16 one(1.0);
86+
Real16 one_copy(1.0);
87+
if (check_exact_value(one, one_copy)) {
88+
std::cout << "✓ PASS: Exact values correctly identified as equal\n";
89+
} else {
90+
std::cerr << "✗ FAIL: Exact values not recognized as equal\n";
91+
++nrOfFailedTestCases;
92+
}
93+
94+
// Test relative error checking with close values
95+
std::cout << "\nRelative Error Checking:\n";
96+
Real16 x(1.0);
97+
Real16 y(1.0 + 1e-20); // very close
98+
if (check_relative_error(x, y)) {
99+
std::cout << "✓ PASS: Very close values pass threshold check\n";
100+
} else {
101+
std::cerr << "✗ FAIL: Close values should pass threshold\n";
102+
++nrOfFailedTestCases;
103+
}
104+
105+
Real16 z(100.0); // far from x
106+
if (!check_relative_error(x, z)) {
107+
std::cout << "✓ PASS: Distant values correctly rejected\n";
108+
} else {
109+
std::cerr << "✗ FAIL: Distant values should be rejected\n";
110+
++nrOfFailedTestCases;
111+
}
112+
113+
// Summary
114+
std::cout << "\n=================================================\n";
115+
if (nrOfFailedTestCases == 0) {
116+
std::cout << "SUCCESS: All adaptive threshold tests passed!\n";
117+
} else {
118+
std::cout << "FAILED: " << nrOfFailedTestCases << " test(s) failed\n";
119+
}
120+
121+
return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
122+
}
123+
catch (char const* msg) {
124+
std::cerr << "Caught exception: " << msg << std::endl;
125+
return EXIT_FAILURE;
126+
}
127+
catch (...) {
128+
std::cerr << "Caught unknown exception" << std::endl;
129+
return EXIT_FAILURE;
130+
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// adaptive_threshold.cpp: test suite for adaptive threshold utilities
2+
//
3+
// Copyright (C) 2017 Stillwater Supercomputing, Inc.
4+
// SPDX-License-Identifier: MIT
5+
//
6+
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
7+
#include <universal/utility/directives.hpp>
8+
#include <universal/number/ereal/ereal.hpp>
9+
#include <universal/verification/test_suite.hpp>
10+
#include <universal/verification/test_suite_mathlib_adaptive.hpp>
11+
12+
int main()
13+
try {
14+
using namespace sw::universal;
15+
16+
std::string test_suite = "ereal adaptive threshold utilities";
17+
int nrOfFailedTestCases = 0;
18+
19+
std::cout << "Adaptive Threshold Utilities Test\n";
20+
std::cout << "==================================\n";
21+
22+
// Test 1: Verify adaptive thresholds scale with precision
23+
{
24+
std::cout << "\nTest 1: Adaptive threshold scaling\n";
25+
26+
double threshold_double = get_adaptive_threshold<double>();
27+
std::cout << " double threshold (digits10=" << std::numeric_limits<double>::digits10
28+
<< "): " << threshold_double << "\n";
29+
30+
using Real32 = ereal<32>;
31+
double threshold_ereal32 = get_adaptive_threshold<Real32>();
32+
std::cout << " ereal<32> threshold (digits10=" << std::numeric_limits<Real32>::digits10
33+
<< "): " << threshold_ereal32 << "\n";
34+
35+
// ereal should have tighter threshold if it has more precision
36+
if (std::numeric_limits<Real32>::digits10 > std::numeric_limits<double>::digits10) {
37+
if (threshold_ereal32 >= threshold_double) {
38+
std::cerr << "FAIL: ereal<32> should have tighter threshold than double\n";
39+
++nrOfFailedTestCases;
40+
}
41+
}
42+
}
43+
44+
// Test 2: Verify exact value checking
45+
{
46+
std::cout << "\nTest 2: Exact value checking\n";
47+
48+
using Real = ereal<16>;
49+
Real one(1.0);
50+
Real also_one(1.0);
51+
Real not_quite_one(1.0000001);
52+
53+
if (!check_exact_value(one, also_one)) {
54+
std::cerr << "FAIL: exact value check should pass for identical values\n";
55+
++nrOfFailedTestCases;
56+
} else {
57+
std::cout << " PASS: exact value check for identical values\n";
58+
}
59+
60+
if (check_exact_value(one, not_quite_one)) {
61+
std::cerr << "FAIL: exact value check should fail for different values\n";
62+
++nrOfFailedTestCases;
63+
} else {
64+
std::cout << " PASS: exact value check correctly rejects different values\n";
65+
}
66+
}
67+
68+
// Test 3: Verify relative error checking
69+
{
70+
std::cout << "\nTest 3: Relative error checking\n";
71+
72+
using Real = ereal<16>;
73+
Real x(1.0);
74+
Real y(1.0 + 1e-16); // very close to x
75+
76+
if (!check_relative_error(x, y)) {
77+
std::cerr << "FAIL: relative error check should pass for very close values\n";
78+
++nrOfFailedTestCases;
79+
} else {
80+
std::cout << " PASS: relative error check for close values\n";
81+
}
82+
83+
Real z(2.0); // far from x
84+
if (check_relative_error(x, z)) {
85+
std::cerr << "FAIL: relative error check should fail for distant values\n";
86+
++nrOfFailedTestCases;
87+
} else {
88+
std::cout << " PASS: relative error check correctly rejects distant values\n";
89+
}
90+
}
91+
92+
// Test 4: Verify identity checking
93+
{
94+
std::cout << "\nTest 4: Identity checking\n";
95+
96+
using Real = ereal<16>;
97+
Real x(1.5);
98+
Real lhs = x * x; //
99+
Real rhs = x * x; // should be identical
100+
101+
int failures = verify_identity("x² == x²", lhs, rhs, 0.0, false);
102+
if (failures != 0) {
103+
std::cerr << "FAIL: identity check failed for identical expressions\n";
104+
++nrOfFailedTestCases;
105+
} else {
106+
std::cout << " PASS: identity check for identical expressions\n";
107+
}
108+
}
109+
110+
// Test 5: Error reporting (manual check - should print nicely formatted output)
111+
{
112+
std::cout << "\nTest 5: Error reporting format\n";
113+
std::cout << " (The following is a test of error reporting format, not a real failure)\n";
114+
115+
using Real = ereal<16>;
116+
Real result(2.71828);
117+
Real expected(2.71829);
118+
double threshold = get_adaptive_threshold<Real>();
119+
120+
std::cout << " Sample error report:\n";
121+
std::cout << " --------------------\n";
122+
report_error_detail("exp", "1.0", result, expected, threshold, true);
123+
std::cout << " --------------------\n";
124+
}
125+
126+
std::cout << "\n";
127+
if (nrOfFailedTestCases > 0) {
128+
std::cout << "FAILED: " << nrOfFailedTestCases << " test case(s)\n";
129+
} else {
130+
std::cout << "SUCCESS: All adaptive threshold utility tests passed\n";
131+
}
132+
133+
return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
134+
}
135+
catch (char const* msg) {
136+
std::cerr << "Caught ad-hoc exception: " << msg << std::endl;
137+
return EXIT_FAILURE;
138+
}
139+
catch (const sw::universal::universal_arithmetic_exception& err) {
140+
std::cerr << "Caught unexpected universal arithmetic exception: " << err.what() << std::endl;
141+
return EXIT_FAILURE;
142+
}
143+
catch (const sw::universal::universal_internal_exception& err) {
144+
std::cerr << "Caught unexpected universal internal exception: " << err.what() << std::endl;
145+
return EXIT_FAILURE;
146+
}
147+
catch (const std::runtime_error& err) {
148+
std::cerr << "Caught unexpected runtime exception: " << err.what() << std::endl;
149+
return EXIT_FAILURE;
150+
}
151+
catch (...) {
152+
std::cerr << "Caught unknown exception" << std::endl;
153+
return EXIT_FAILURE;
154+
}

elastic/ereal/api/api.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,40 @@ try {
181181
// std::cout << "polynomial(1.0) = " << polyeval(polynomial, 5, ereal(1.0f)) << '\n';
182182
}
183183

184+
std::cout << "Basic ereal<16> operations test\n";
185+
std::cout << "================================\n\n";
186+
{
187+
using Real = ereal<16>;
188+
189+
std::cout << "Creating x = 1.0...\n";
190+
Real x(1.0);
191+
std::cout << "x = " << x << "\n";
192+
193+
std::cout << "\nCreating y = 2.0...\n";
194+
Real y(2.0);
195+
std::cout << "y = " << y << "\n";
196+
197+
std::cout << "\nComputing x + y...\n";
198+
Real sum = x + y;
199+
std::cout << "x + y = " << sum << "\n";
200+
201+
std::cout << "\nComputing x - y...\n";
202+
Real diff = x - y;
203+
std::cout << "x - y = " << diff << "\n";
204+
205+
std::cout << "\nComputing abs(x - y)...\n";
206+
Real abs_diff = abs(diff);
207+
std::cout << "abs(x - y) = " << abs_diff << "\n";
208+
209+
std::cout << "\nComputing (x - y) / y...\n";
210+
Real rel_err = diff / y;
211+
std::cout << "(x - y) / y = " << rel_err << "\n";
212+
213+
std::cout << "\nConverting to double...\n";
214+
double rel_err_d = double(rel_err);
215+
std::cout << "as double: " << rel_err_d << "\n";
216+
}
217+
184218
ReportTestSuiteResults(test_suite, nrOfFailedTestCases);
185219
return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
186220
}

0 commit comments

Comments
 (0)