Skip to content

Commit c294759

Browse files
committed
Another bash on midpoint and lerp now that it looks like it might go in.
1 parent bcde1f6 commit c294759

File tree

5 files changed

+183
-29
lines changed

5 files changed

+183
-29
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CXX = /home/ed/bin/bin/g++ -std=c++17 -g
1+
CXX = /home/ed/bin/bin/g++ -std=c++17 -g -Wall -Wextra
22

33
all: test_lerp test_midpoint
44

lerp.h

+12-6
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,24 @@ namespace std
1212
{
1313
if (std::isnan(__a) || std::isnan(__b) || std::isnan(__t))
1414
return std::numeric_limits<_Float>::quiet_NaN();
15-
else if (__a <= _Float{0} && __b >= _Float{0}
16-
|| __a >= _Float{0} && __b <= _Float{0})
15+
else if ((__a <= _Float{0} && __b >= _Float{0})
16+
|| (__a >= _Float{0} && __b <= _Float{0}))
1717
// ab <= 0 but product could overflow.
18-
//return __t * __b + (_Float{1} - __t) * __a;
19-
return std::fma(__t, __b, (_Float{1} - __t) * __a)
18+
#ifndef FMA
19+
return __t * __b + (_Float{1} - __t) * __a;
20+
#else
21+
return std::fma(__t, __b, (_Float{1} - __t) * __a);
22+
#endif
2023
else if (__t == _Float{1})
2124
return __b;
2225
else
2326
{ // monotonic near t == 1.
24-
//const auto __x = __a + __t * (__b - __a);
27+
#ifndef FMA
28+
const auto __x = __a + __t * (__b - __a);
29+
#else
2530
const auto __x = std::fma(__t, __b - __a, __a);
26-
return __t > _Float{1} == __b > __a
31+
#endif
32+
return (__t > _Float{1}) == (__b > __a)
2733
? std::max(__b, __x)
2834
: std::min(__b, __x);
2935
}

midpoint.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define MIDPOINT_H 1
33

44
#include <cmath>
5+
#include <cstdint>
56

67
namespace std
78
{
@@ -12,6 +13,12 @@ namespace std
1213
midpoint(_Int __a, _Int __b) noexcept
1314
{
1415
using _UInt = std::make_unsigned_t<_Int>;
16+
/*
17+
const auto __ua = _UInt(__a);
18+
const auto __ub = _UInt(__b);
19+
const auto __del = (__ub > __ua ? +(__ub - __ua) : -(__ua - __ub));
20+
return _Int(__ua + __del / 2);
21+
*/
1522
return _Int(_UInt(__a) + (_UInt(__b) - _UInt(__a)) / 2);
1623
}
1724

@@ -31,7 +38,12 @@ namespace std
3138
template<typename _Tp>
3239
_Tp*
3340
midpoint(_Tp* __a, _Tp* __b)
34-
{ return static_cast<_Tp*>(std::midpoint(intptr_t(__a), intptr_t(__b))); }
41+
{
42+
//using _Iptr = std::intptr_t;
43+
//return static_cast<_Tp*>(__a + std::midpoint(_Iptr(__a), _Iptr(__b)));
44+
const auto __diff = (__b - __a) / 2;
45+
return __a + __diff;
46+
}
3547

3648
} // namespace std
3749

test_lerp.cpp

+93-20
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
/home/ed/bin/bin/g++ -std=c++17 -o test_lerp test_lerp.cpp
2+
/home/ed/bin/bin/g++ -std=c++17 -g -Wall -Wextra -o test_lerp test_lerp.cpp
33
*/
44

55
#include <limits>
@@ -9,33 +9,76 @@
99

1010
#include <iostream>
1111

12+
template<typename Real>
13+
bool
14+
test()
15+
{
16+
const auto a = Real{5};
17+
const auto b = Real{10};
18+
const auto t = Real{0.75L};
19+
const auto x = std::lerp(a, b, t);
20+
21+
std::cout << "x = " << x << '\n';
22+
23+
return true;
24+
}
25+
1226
template<typename Real>
1327
bool
1428
test_ends()
1529
{
1630
const auto a = Real{-3};
1731
const auto b = Real{+5};
18-
const auto t = Real{3} / Real{4};
19-
auto ca = std::lerp(a, b, Real{0});
32+
33+
const auto ca = std::lerp(a, b, Real{0});
2034
std::cout << "ca = " << ca << '\n';
21-
std::cout << std::boolalpha << "ca == a: " << (ca == a) << '\n';
22-
auto cb = std::lerp(a, b, Real{1});
35+
std::cout << "ca == a: " << std::boolalpha << (ca == a) << '\n';
36+
37+
const auto cb = std::lerp(a, b, Real{1});
2338
std::cout << "cb = " << cb << '\n';
24-
std::cout << std::boolalpha << "cb == b: " << (cb == b) << '\n';
39+
std::cout << "cb == b: " << std::boolalpha << (cb == b) << '\n';
40+
2541
return ca == a && cb == b;
2642
}
2743

2844
template<typename Real>
2945
bool
30-
test_huge()
46+
test_nan()
3147
{
32-
const auto a = -std::numeric_limits<Real>::max();
33-
const auto b = +std::numeric_limits<Real>::max();
34-
const auto t = Real{3} / Real{4};
35-
auto c = std::lerp(a, b, t);
36-
std::cout << "c = " << c << '\n';
37-
std::cout << std::boolalpha << "c == b/2: " << (c == b / Real{2}) << '\n';
38-
return c == b / Real{2};
48+
const auto a = Real{5};
49+
const auto b = Real{10};
50+
const auto t = Real{0.75L};
51+
52+
const auto anan = std::numeric_limits<Real>::quiet_NaN();
53+
const auto bnan = std::numeric_limits<Real>::quiet_NaN();
54+
const auto tnan = std::numeric_limits<Real>::quiet_NaN();
55+
56+
const auto nan = std::isnan(std::lerp(anan, b, t))
57+
&& std::isnan(std::lerp(a, bnan, t))
58+
&& std::isnan(std::lerp(a, b, tnan));
59+
60+
std::cout << "nan: " << std::boolalpha << nan << '\n';
61+
62+
return nan;
63+
}
64+
65+
template<typename Real>
66+
bool
67+
test_subnorm()
68+
{
69+
const auto denorm = std::numeric_limits<Real>::denorm_min();
70+
71+
const auto a = Real{5} * denorm;
72+
const auto b = Real{10} * denorm;
73+
const auto t = Real{0.75L};
74+
const auto x = std::lerp(a, b, t);
75+
std::cout << "x: " << x / denorm << '\n';
76+
77+
const auto a00 = Real{500} * denorm;
78+
const auto b00 = Real{1000} * denorm;
79+
const auto x00 = std::lerp(a00, b00, t);
80+
std::cout << "x00: " << x00 / denorm << '\n';
81+
return true;
3982
}
4083

4184
template<typename Real>
@@ -45,28 +88,58 @@ template<typename Real>
4588
const auto a = Real{5};
4689
const auto b = a;
4790
const auto t = std::numeric_limits<Real>::infinity();
48-
auto c = std::lerp(a, b, t);
91+
const auto c = std::lerp(a, b, t);
4992
std::cout << "c = " << c << '\n';
50-
std::cout << std::boolalpha << "c == a: " << (c == a) << '\n';
93+
std::cout << "c == a: " << std::boolalpha << (c == a) << '\n';
5194
return c == a;
5295
}
5396

97+
template<typename Real>
98+
bool
99+
test_huge()
100+
{
101+
const auto max = std::numeric_limits<Real>::max() / 16;
102+
const auto a = Real{5} * max;
103+
const auto b = Real{10} * max;
104+
const auto t = Real{3} / Real{4};
105+
const auto c = std::lerp(a, b, t);
106+
std::cout << "c = " << c / max << '\n';
107+
std::cout << "c == b/2: " << std::boolalpha << (c == Real{8.75} * max) << '\n';
108+
return c == b / Real{2};
109+
}
110+
54111
int
55112
main()
56113
{
57114
bool ok = true;
58115

116+
std::cout << "\ntest\n";
117+
ok = ok && test<float>();
118+
ok = ok && test<double>();
119+
ok = ok && test<long double>();
120+
121+
std::cout << "\ntest_nan\n";
122+
ok = ok && test_nan<float>();
123+
ok = ok && test_nan<double>();
124+
ok = ok && test_nan<long double>();
125+
126+
std::cout << "\ntest_ends\n";
59127
ok = ok && test_ends<float>();
60128
ok = ok && test_ends<double>();
61129
ok = ok && test_ends<long double>();
62130

63-
ok = ok && test_huge<float>();
64-
ok = ok && test_huge<double>();
65-
ok = ok && test_huge<long double>();
66-
131+
std::cout << "\ntest_inf\n";
67132
ok = ok && test_inf<float>();
68133
ok = ok && test_inf<double>();
69134
ok = ok && test_inf<long double>();
70135

136+
std::cout << "\ntest_subnorm\n";
137+
ok = ok && test_subnorm<float>();
138+
139+
std::cout << "\ntest_huge\n";
140+
ok = ok && test_huge<float>();
141+
ok = ok && test_huge<double>();
142+
ok = ok && test_huge<long double>();
143+
71144
return ok;
72145
}

test_midpoint.cpp

+64-1
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,79 @@
11
/*
2-
/home/ed/bin/bin/g++ -std=c++17 -o test_midpoint test_midpoint.cpp
2+
/home/ed/bin/bin/g++ -std=c++17 -g -Wall -Wextra -o test_midpoint test_midpoint.cpp
33
*/
44

55
#include <limits>
66
#include <type_traits>
77

88
#include "midpoint.h"
99

10+
#include <iostream>
11+
12+
template<typename Int>
13+
bool
14+
test_twos_comp()
15+
{
16+
const std::make_unsigned_t<Int> a = 10, b = 5;
17+
const auto mab = std::midpoint(a, b);
18+
std::cout << "mab = " << int(mab) << '\n';
19+
20+
return true;
21+
}
22+
23+
template<typename Real>
24+
bool
25+
test_huge()
26+
{
27+
const auto huge = std::numeric_limits<Real>::max();
28+
const auto a = -huge;
29+
const auto b = +huge;
30+
const auto c = std::midpoint(a, b);
31+
std::cout << "c = " << c << '\n';
32+
std::cout << "c == 0: " << std::boolalpha << (c == Real{0}) << '\n';
33+
return c == Real{0};
34+
}
35+
36+
template<typename Tp>
37+
bool
38+
test_ptr()
39+
{
40+
constexpr int num = 21;
41+
constexpr Tp arr[num]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
42+
const auto a = arr;
43+
const auto b = arr + num;
44+
auto ab = std::midpoint(a, b);
45+
std::cout << "a = " << a << "; b = " << b << "; ab = " << ab << '\n';
46+
std::cout << "ab - a = " << ab - a << "; ab - b = " << ab - b << '\n';
47+
std::cout << "ab = " << ab << "; *ab = " << *ab << '\n';
48+
auto ba = std::midpoint(b-1, a-1); // rbegin, rend
49+
std::cout << "ba - (b-1) = " << ba - (b-1) << "; ba - (a-1) = " << ba - (a-1) << '\n';
50+
std::cout << "ba = " << ba << "; *ba = " << *ba << '\n';
51+
return true;
52+
}
53+
1054
int
1155
main()
1256
{
1357
bool ok = true;
1458

59+
const int a = 5, b = 10;
60+
const auto mab = std::midpoint(a, b);
61+
std::cout << "mab = " << mab << '\n';
62+
63+
std::cout << "\ntest_huge\n";
64+
ok = ok && test_huge<float>();
65+
ok = ok && test_huge<double>();
66+
ok = ok && test_huge<long double>();
67+
68+
std::cout << "\ntest_twos_comp\n";
69+
ok = ok && test_twos_comp<unsigned char>();
70+
ok = ok && test_twos_comp<short>();
71+
ok = ok && test_twos_comp<int>();
72+
ok = ok && test_twos_comp<long>();
73+
ok = ok && test_twos_comp<long long>();
74+
75+
std::cout << "\ntest_ptr\n";
76+
ok = ok && test_ptr<int>();
77+
1578
return ok;
1679
}

0 commit comments

Comments
 (0)