1
- // Copyright (c) Six Labors.
1
+ // Copyright (c) Six Labors.
2
2
// Licensed under the Six Labors Split License.
3
3
4
4
using System ;
5
5
using System . Collections . Generic ;
6
6
using System . Diagnostics ;
7
+ using System . Runtime . CompilerServices ;
8
+ using System . Runtime . InteropServices ;
7
9
8
10
namespace PolygonClipper ;
9
11
@@ -16,14 +18,18 @@ namespace PolygonClipper;
16
18
internal sealed class StablePriorityQueue < T , TComparer >
17
19
where TComparer : IComparer < T >
18
20
{
19
- private readonly List < T > heap = [ ] ;
21
+ private readonly List < T > heap ;
20
22
21
23
/// <summary>
22
24
/// Initializes a new instance of the <see cref="StablePriorityQueue{T, TComparer}"/> class with a specified comparer.
23
25
/// </summary>
24
26
/// <param name="comparer">The comparer to determine the priority of the elements.</param>
25
- public StablePriorityQueue ( TComparer comparer )
26
- => this . Comparer = comparer ?? throw new ArgumentNullException ( nameof ( comparer ) ) ;
27
+ /// <param name="capacity">The initial capacity of the priority queue.</param>
28
+ public StablePriorityQueue ( TComparer comparer , int capacity )
29
+ {
30
+ this . Comparer = comparer ?? throw new ArgumentNullException ( nameof ( comparer ) ) ;
31
+ this . heap = new List < T > ( capacity > 0 ? capacity : 16 ) ;
32
+ }
27
33
28
34
/// <summary>
29
35
/// Gets the number of elements in the priority queue.
@@ -42,7 +48,7 @@ public StablePriorityQueue(TComparer comparer)
42
48
public void Enqueue ( T item )
43
49
{
44
50
this . heap . Add ( item ) ;
45
- this . Up ( this . heap . Count - 1 ) ;
51
+ this . Up ( ( uint ) this . heap . Count - 1 ) ;
46
52
}
47
53
48
54
/// <summary>
@@ -86,61 +92,66 @@ public T Peek()
86
92
}
87
93
88
94
/// <summary>
89
- /// Restores the heap property by moving the item at the specified index upward.
95
+ /// Restores the min-heap property by moving the item at the specified index upward
96
+ /// through the heap until it is in the correct position. This is called after insertion.
90
97
/// </summary>
91
- /// <param name="index">The index of the item to move upward.</param>
92
- private void Up ( int index )
98
+ /// <param name="index">The index of the newly added item to sift upward.</param>
99
+ private void Up ( uint index )
93
100
{
94
- List < T > data = this . heap ;
95
- T item = data [ index ] ;
101
+ ref T dRef = ref MemoryMarshal . GetReference ( CollectionsMarshal . AsSpan ( this . heap ) ) ;
102
+ T item = Unsafe . Add ( ref dRef , index ) ;
96
103
TComparer comparer = this . Comparer ;
97
104
98
105
while ( index > 0 )
99
106
{
100
- int parent = ( index - 1 ) >> 1 ;
101
- T current = data [ parent ] ;
107
+ uint parent = ( index - 1u ) >> 1 ;
108
+ T current = Unsafe . Add ( ref dRef , parent ) ;
102
109
if ( comparer . Compare ( item , current ) >= 0 )
103
110
{
104
111
break ;
105
112
}
106
113
107
- data [ index ] = current ;
114
+ Unsafe . Add ( ref dRef , index ) = current;
108
115
index = parent ;
109
116
}
110
117
111
- data [ index ] = item ;
118
+ Unsafe . Add ( ref dRef , index ) = item;
112
119
}
113
120
114
121
/// <summary>
115
- /// Restores the heap property by moving the item at the specified index downward.
122
+ /// Restores the min-heap property by moving the item at the specified index downward
123
+ /// through the heap until it is in the correct position. This is called after removal of the root.
116
124
/// </summary>
117
- /// <param name="index">The index of the item to move downward.</param>
118
- private void Down ( int index )
125
+ /// <param name="index">The index of the item to sift downward (typically the root) .</param>
126
+ private void Down ( uint index )
119
127
{
120
- List < T > data = this . heap ;
121
- int halfLength = data . Count >> 1 ;
122
- T item = data [ index ] ;
128
+ Span < T > data = CollectionsMarshal . AsSpan ( this . heap ) ;
129
+ ref T dRef = ref MemoryMarshal . GetReference ( data ) ;
130
+
131
+ uint length = ( uint ) data . Length ;
132
+ uint halfLength = length >> 1 ;
133
+ T item = Unsafe . Add ( ref dRef , index ) ;
123
134
TComparer comparer = this . Comparer ;
124
135
125
136
while ( index < halfLength )
126
137
{
127
- int bestChild = ( index << 1 ) + 1 ; // Initially left child
128
- int right = bestChild + 1 ;
138
+ uint bestChild = ( index << 1 ) + 1 ; // Initially left child
139
+ uint right = bestChild + 1u ;
129
140
130
- if ( right < data . Count && comparer . Compare ( data [ right ] , data [ bestChild ] ) < 0 )
141
+ if ( right < length && comparer . Compare ( Unsafe . Add ( ref dRef , right ) , Unsafe . Add ( ref dRef , bestChild ) ) < 0 )
131
142
{
132
143
bestChild = right ;
133
144
}
134
145
135
- if ( comparer . Compare ( data [ bestChild ] , item ) >= 0 )
146
+ if ( comparer . Compare ( Unsafe . Add ( ref dRef , bestChild ) , item ) >= 0 )
136
147
{
137
148
break ;
138
149
}
139
150
140
- data [ index ] = data [ bestChild ] ;
151
+ Unsafe . Add ( ref dRef , index ) = Unsafe . Add ( ref dRef , bestChild ) ;
141
152
index = bestChild ;
142
153
}
143
154
144
- data [ index ] = item ;
155
+ Unsafe . Add ( ref dRef , index ) = item;
145
156
}
146
157
}
0 commit comments