Skip to content

Commit 5755d97

Browse files
committed
Use built in binary search for interpolating mat
1 parent 01d7ec4 commit 5755d97

File tree

1 file changed

+29
-45
lines changed

1 file changed

+29
-45
lines changed

src/wpimath/Interpolation/InterpolatingMap.cs

Lines changed: 29 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,18 @@
22

33
namespace WPIMath.Interpolation;
44

5-
public class InterpolatingMap<T>(IComparer<T> comparer) where T : notnull,
5+
public class InterpolatingMap<T> where T : struct,
66
IFloatingPointIeee754<T>
77
{
88
// TODO find a better solution to this
99
private readonly List<(T key, T value)> m_map = [];
10-
private readonly Comparison<(T key, T value)> m_comparer = (a, b) => comparer.Compare(a.key, b.key);
11-
private readonly IComparer<T> m_keyComparer = comparer;
12-
13-
public InterpolatingMap() : this(Comparer<T>.Default)
14-
{
15-
}
10+
private readonly IComparer<(T key, T value)> m_comparer = new KeyCoercingComparer();
1611

1712
public void Add(T key, T value)
1813
{
19-
int idx = m_map.FindIndex(x => m_keyComparer.Compare(x.key, key) == 0);
20-
if (idx < 0)
21-
{
22-
m_map.Add((key, value));
23-
}
24-
else
25-
{
26-
var val = m_map[idx];
27-
m_map[idx] = (key, val.value);
28-
}
29-
m_map.Sort(m_comparer);
14+
// Doing this ensures the tree is always sorted.
15+
int idx = m_map.BinarySearch((key, value), m_comparer);
16+
m_map.Insert(~idx, (key, value));
3017
}
3118

3219
public T this[T key]
@@ -38,38 +25,26 @@ public T this[T key]
3825
return T.Zero;
3926
}
4027

41-
// List is already sorted
42-
(T key, T value) lower = m_map[0];
43-
(T key, T value) upper = m_map[^1];
28+
int idx = m_map.BinarySearch((key, T.Zero));
29+
if (idx >= 0) {
30+
return m_map[idx].value;
31+
}
4432

45-
// Binary search
46-
int minimum = 0;
47-
int maximum = m_map.Count - 1;
48-
while (minimum <= maximum)
49-
{
50-
int midpoint = (minimum + maximum) / 2;
51-
int compare = m_keyComparer.Compare(key, m_map[midpoint].key);
52-
if (compare == 0)
53-
{
54-
return m_map[midpoint].value;
55-
}
56-
else if (compare < 0)
57-
{
58-
upper = m_map[midpoint];
59-
maximum = midpoint - 1;
60-
}
61-
else
62-
{
63-
lower = m_map[midpoint];
64-
minimum = midpoint + 1;
65-
}
33+
int larger = ~idx;
34+
35+
// Request is smaller than all elements, return smallest
36+
if (larger == 0) {
37+
return m_map[larger].value;
6638
}
6739

68-
if (m_comparer(lower, upper) == 0)
69-
{
70-
return lower.value;
40+
// Request is larger than all elements, return largest
41+
if (larger == m_map.Count) {
42+
return m_map[^1].value;
7143
}
7244

45+
(T key, T value) lower = m_map[larger - 1];
46+
(T key, T value) upper = m_map[larger];
47+
7348
T delta = (key - lower.key) / (upper.key - lower.key);
7449
return T.Lerp(lower.value, upper.value, delta);
7550
}
@@ -79,4 +54,13 @@ public void Clear()
7954
{
8055
m_map.Clear();
8156
}
57+
58+
private sealed class KeyCoercingComparer : IComparer<(T key, T value)>
59+
{
60+
public int Compare((T key, T value) x, (T key, T value) y)
61+
{
62+
int result = x.key.CompareTo(y.key);
63+
return result;
64+
}
65+
}
8266
}

0 commit comments

Comments
 (0)