Skip to content

Commit 9da8db3

Browse files
committed
Adding Kahan's Smooth Surprise to Applications. Also moved Rump to the accuracy/mathemetics area
1 parent b0c606e commit 9da8db3

File tree

7 files changed

+236
-19
lines changed

7 files changed

+236
-19
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// harmonic_series.cpp: experiments with mixed-precision representations of the Harmonic Series
2+
//
3+
// Copyright (C) 2017 Stillwater Supercomputing, Inc.
4+
// SPDX-License-Identifier: MIT
5+
//
6+
// This file is part of the UNIVERSAL project, which is released under an MIT Open Source license.
7+
#include <universal/utility/directives.hpp>
8+
#include <iostream>
9+
#include <iomanip>
10+
11+
#include <universal/number/posit/posit.hpp>
12+
#include <universal/number/cfloat/cfloat.hpp>
13+
#include <universal/number/dd/dd.hpp>
14+
#include <universal/number/qd/qd.hpp>
15+
16+
#include <universal/number/rational/rational.hpp>
17+
18+
namespace sw {
19+
namespace universal {
20+
21+
22+
23+
template<typename Scalar>
24+
Scalar f(Scalar x) {
25+
using std::log, std::abs;
26+
return log(abs(3 * (1 - x) + 1)) / 80 + x * x + 1;
27+
}
28+
29+
template<typename Scalar>
30+
void report_on_f(Scalar x) {
31+
Scalar f_of_x = f(x);
32+
std::cout << "f(" << x << ") = " << to_binary(f_of_x) << " : " << f_of_x << '\n';
33+
}
34+
35+
// Kahan's Smooth Surprise: minimize log(abs(3(1-x) + 1))/80 + x^2 + 1 in the interval [0.8, 2.0]
36+
template<typename Scalar>
37+
Scalar smooth_surprise(int samples = 10) {
38+
39+
Scalar x{ 0.8 };
40+
Scalar dx = Scalar(1.2) / Scalar(samples);
41+
Scalar min = std::numeric_limits<Scalar>::max();
42+
for (int i = 0; i < samples; ++i) {
43+
Scalar y = f(x);
44+
if (y < min) min = y;
45+
//std::cout << std::setw(10) << i << " : " << x << " : " << y << '\n';
46+
x += dx;
47+
}
48+
return min;
49+
50+
}
51+
52+
53+
}
54+
}
55+
56+
int main()
57+
try {
58+
using namespace sw::universal;
59+
60+
int samples = 1024 * 512;
61+
std::cout << "minimum = " << smooth_surprise<float>(samples) << '\n';
62+
63+
float f_4{ 4.0 }, f_3{ 3.0 }, f_4_3 = f_4 / f_3;
64+
report_on_f(f_4_3);
65+
double d_4{ 4.0 }, d_3{ 3.0 }, d_4_3 = d_4 / d_3;
66+
report_on_f(d_4_3);
67+
dd dd_4{ 4.0 }, dd_3{ 3.0 }, dd_4_3 = dd_4 / dd_3;
68+
report_on_f(dd_4_3);
69+
qd qd_4{ 4.0 }, qd_3{ 3.0 }, qd_4_3 = qd_4 / qd_3;
70+
report_on_f(qd_4_3);
71+
72+
rational<64> r_4{ 4 }, r_3{ 3 }, r_4_3 = r_4 / r_3;
73+
report_on_f(r_4_3);
74+
}
75+
catch(...) {
76+
}
77+
Loading

applications/precision/numeric/rump_equation.cpp renamed to applications/accuracy/mathematics/rump_equation.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include <universal/number/cfloat/cfloat.hpp>
1717
#include <universal/number/posit/posit.hpp>
1818
#include <universal/number/lns/lns.hpp>
19+
#include <universal/number/dd/dd.hpp>
20+
#include <universal/number/qd/qd.hpp>
1921

2022
#include <universal/blas/blas.hpp>
2123

@@ -195,12 +197,12 @@ There are a couple fpbench versions of it: https://fpbench.org/benchmarks.html#
195197
"posit80",
196198
"posit128",
197199
"posit156",
198-
"bfloat16",
199-
"bfloat32",
200-
"bfloat64",
201-
"bfloat80",
202-
"bfloat100",
203-
"bfloat120"
200+
"cfloat16",
201+
"cfloat32",
202+
"cfloat64",
203+
"cfloat80",
204+
"dd",
205+
"qd"
204206
};
205207
Labels column = {
206208
"Rump1",
@@ -221,6 +223,12 @@ There are a couple fpbench versions of it: https://fpbench.org/benchmarks.html#
221223
GenerateRow<posit<80, 2>>(a, b, table, 8);
222224
GenerateRow<posit<128, 2>>(a, b, table, 9);
223225
GenerateRow<posit<156, 2>>(a, b, table, 10);
226+
GenerateRow<cfloat<16, 11, std::uint16_t, true>>(a, b, table, 11);
227+
GenerateRow<cfloat<32, 11, std::uint32_t, true>>(a, b, table, 12);
228+
GenerateRow<cfloat<64, 11, std::uint64_t, true>>(a, b, table, 13);
229+
GenerateRow<cfloat<80, 11, std::uint64_t, true>>(a, b, table, 14);
230+
GenerateRow<dd>(a, b, table, 15);
231+
GenerateRow<qd>(a, b, table, 16);
224232

225233
// print the table
226234
constexpr size_t COLUMN_WIDTH = 20;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#pragma once
2+
// logarithm.hpp: logarithm functions for rational
3+
//
4+
// Copyright (C) 2017 Stillwater Supercomputing, Inc.
5+
// SPDX-License-Identifier: MIT
6+
//
7+
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
8+
9+
namespace sw { namespace universal {
10+
11+
// Natural logarithm of x
12+
template<unsigned nbits, typename bt>
13+
rational<nbits, bt> log(rational<nbits, bt> x) {
14+
return rational<nbits, bt>(std::log(double(x)));
15+
}
16+
17+
// Binary logarithm of x
18+
template<unsigned nbits, typename bt>
19+
rational<nbits, bt> log2(rational<nbits, bt> x) {
20+
return rational<nbits, bt>(std::log2(double(x)));
21+
}
22+
23+
// Decimal logarithm of x
24+
template<unsigned nbits, typename bt>
25+
rational<nbits, bt> log10(rational<nbits, bt> x) {
26+
return rational<nbits, bt>(std::log10(double(x)));
27+
}
28+
29+
// Natural logarithm of 1+x
30+
template<unsigned nbits, typename bt>
31+
rational<nbits, bt> log1p(rational<nbits, bt> x) {
32+
return rational<nbits, bt>(std::log1p(double(x)));
33+
}
34+
35+
}} // namespace sw::universal
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma once
2+
// minmax.hpp: min/max functions for rational
3+
//
4+
// Copyright (C) 2017 Stillwater Supercomputing, Inc.
5+
// SPDX-License-Identifier: MIT
6+
//
7+
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
8+
9+
namespace sw { namespace universal {
10+
11+
// minimum of two values
12+
template<unsigned nbits, typename bt>
13+
rational<nbits, bt>
14+
min(rational<nbits, bt> x, rational<nbits, bt> y) {
15+
return rational<nbits, bt>(std::min(double(x), double(y)));
16+
}
17+
18+
// maximum of two values
19+
template<unsigned nbits, typename bt>
20+
rational<nbits, bt>
21+
max(rational<nbits, bt> x, rational<nbits, bt> y) {
22+
return rational<nbits, bt>(std::max(double(x), double(y)));
23+
}
24+
25+
26+
}} // namespace sw::universal
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#pragma once
2+
// sqrt.hpp: sqrt functions for rational
3+
//
4+
// Copyright (C) 2017 Stillwater Supercomputing, Inc.
5+
// SPDX-License-Identifier: MIT
6+
//
7+
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
8+
#include <universal/native/ieee754.hpp>
9+
//#include <universal/number/lns/math/sqrt_tables.hpp>
10+
11+
#ifndef LNS_NATIVE_SQRT
12+
#define LNS_NATIVE_SQRT 0
13+
#endif
14+
15+
namespace sw { namespace universal {
16+
17+
/*
18+
- Consider the function argument, x, in floating-point form, with a base
19+
(or radix) B, exponent e, and a fraction, f , such that 1/B <= f < 1.
20+
Then we have x = f Be. The number of bits in the exponent and
21+
fraction, and the value of the base, depends on the particular floating
22+
point arithmetic system chosen.
23+
24+
- Use properties of the elementary function to range reduce the argument
25+
x to a small fixed interval.
26+
27+
- Use a small polynomial approximation to produce an initial estimate,
28+
y0, of the function on the small interval. Such an estimate may
29+
be good to perhaps 5 to 10 bits.
30+
31+
- Apply Newton iteration to refine the result. This takes the form yk =
32+
yk?1/2 + (f /2)/yk?1. In base 2, the divisions by two can be done by
33+
exponent adjustments in floating-point computation, or by bit shifting
34+
in fixed-point computation.
35+
36+
Convergence of the Newton method is quadratic, so the number of
37+
correct bits doubles with each iteration. Thus, a starting point correct
38+
to 7 bits will produce iterates accurate to 14, 28, 56, ... bits. Since the
39+
number of iterations is very small, and known in advance, the loop is
40+
written as straight-line code.
41+
42+
- Having computed the function value for the range-reduced argument,
43+
make whatever adjustments are necessary to produce the function value
44+
for the original argument; this step may involve a sign adjustment,
45+
and possibly a single multiplication and/or addition.
46+
*/
47+
48+
49+
// sqrt for arbitrary rational
50+
template<unsigned nbits, typename bt>
51+
inline rational<nbits, bt> sqrt(const rational<nbits, bt>& a) {
52+
#if RATIONAL_THROW_ARITHMETIC_EXCEPTION
53+
if (a.isneg()) throw rational_negative_sqrt_arg();
54+
#else
55+
if (a.isneg()) std::cerr << "rationalns argument to sqrt is negative: " << a << std::endl;
56+
#endif
57+
if (a.iszero()) return a;
58+
return rational<nbits, bt>(std::sqrt((double)a)); // TBD
59+
}
60+
61+
// reciprocal sqrt
62+
template<unsigned nbits, typename bt>
63+
inline rational<nbits, bt> rsqrt(const rational<nbits, bt>& a) {
64+
rational<nbits, bt> v = sqrt(a);
65+
return v.reciprocate();
66+
}
67+
68+
///////////////////////////////////////////////////////////////////
69+
// specialized sqrt configurations
70+
71+
}} // namespace sw::universal

include/universal/number/rational/mathlib.hpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@
66
//
77
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
88

9-
/*
10-
#include <universal/number/rational/math/classify.hpp>
11-
#include <universal/number/rational/math/complex.hpp>
12-
#include <universal/number/rational/math/error_and_gamma.hpp>
13-
#include <universal/number/rational/math/exponent.hpp>
14-
#include <universal/number/rational/math/fractional.hpp>
15-
#include <universal/number/rational/math/hyperbolic.hpp>
16-
#include <universal/number/rational/math/hypot.hpp>
9+
10+
//#include <universal/number/rational/math/classify.hpp>
11+
//#include <universal/number/rational/math/complex.hpp>
12+
//#include <universal/number/rational/math/error_and_gamma.hpp>
13+
//#include <universal/number/rational/math/exponent.hpp>
14+
//#include <universal/number/rational/math/fractional.hpp>
15+
//#include <universal/number/rational/math/hyperbolic.hpp>
16+
//#include <universal/number/rational/math/hypot.hpp>
1717
#include <universal/number/rational/math/logarithm.hpp>
1818
#include <universal/number/rational/math/minmax.hpp>
19-
#include <universal/number/rational/math/next.hpp>
20-
#include <universal/number/rational/math/pow.hpp>
19+
//#include <universal/number/rational/math/next.hpp>
20+
//#include <universal/number/rational/math/pow.hpp>
2121
#include <universal/number/rational/math/sqrt.hpp>
22-
#include <universal/number/rational/math/trigonometry.hpp>
23-
#include <universal/number/rational/math/truncate.hpp>
24-
*/
22+
//#include <universal/number/rational/math/trigonometry.hpp>
23+
//#include <universal/number/rational/math/truncate.hpp>
24+

0 commit comments

Comments
 (0)