2
2
3
3
namespace WPIMath . Interpolation ;
4
4
5
- public class InterpolatingMap < T > ( IComparer < T > comparer ) where T : notnull ,
5
+ public class InterpolatingMap < T > where T : struct ,
6
6
IFloatingPointIeee754 < T >
7
7
{
8
8
// TODO find a better solution to this
9
9
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 ( ) ;
16
11
17
12
public void Add ( T key , T value )
18
13
{
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 ) ) ;
30
17
}
31
18
32
19
public T this [ T key ]
@@ -38,38 +25,26 @@ public T this[T key]
38
25
return T . Zero ;
39
26
}
40
27
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
+ }
44
32
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 ;
66
38
}
67
39
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 ;
71
43
}
72
44
45
+ ( T key , T value ) lower = m_map [ larger - 1 ] ;
46
+ ( T key , T value ) upper = m_map [ larger ] ;
47
+
73
48
T delta = ( key - lower . key ) / ( upper . key - lower . key ) ;
74
49
return T . Lerp ( lower . value , upper . value , delta ) ;
75
50
}
@@ -79,4 +54,13 @@ public void Clear()
79
54
{
80
55
m_map . Clear ( ) ;
81
56
}
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
+ }
82
66
}
0 commit comments