1
- using System . Collections . Generic ;
1
+ using System ;
2
+ using System . Collections . Generic ;
2
3
using System . Text ;
4
+ using System . Threading ;
3
5
4
6
namespace QRCoder
5
7
{
@@ -8,21 +10,132 @@ public partial class QRCodeGenerator
8
10
/// <summary>
9
11
/// Represents a polynomial, which is a sum of polynomial terms.
10
12
/// </summary>
11
- private struct Polynom
13
+ private struct Polynom : IDisposable
12
14
{
15
+ private PolynomItem [ ] _polyItems ;
16
+ private int _length ;
17
+
13
18
/// <summary>
14
19
/// Initializes a new instance of the <see cref="Polynom"/> struct with a specified number of initial capacity for polynomial terms.
15
20
/// </summary>
16
21
/// <param name="count">The initial capacity of the polynomial items list.</param>
17
22
public Polynom ( int count )
18
23
{
19
- this . PolyItems = new List < PolynomItem > ( count ) ;
24
+ _length = 0 ;
25
+ _polyItems = Allocate ( count ) ;
26
+ }
27
+
28
+ /// <summary>
29
+ /// Adds a polynomial term to the polynomial.
30
+ /// </summary>
31
+ public void Add ( PolynomItem item )
32
+ {
33
+ EnsureCapacity ( _length + 1 ) ;
34
+ _polyItems [ _length ++ ] = item ;
35
+ }
36
+
37
+ /// <summary>
38
+ /// Removes the polynomial term at the specified index.
39
+ /// </summary>
40
+ public void RemoveAt ( int index )
41
+ {
42
+ if ( index < 0 || index >= _length )
43
+ throw new IndexOutOfRangeException ( ) ;
44
+
45
+ if ( index < _length - 1 )
46
+ Array . Copy ( _polyItems , index + 1 , _polyItems , index , _length - index - 1 ) ;
47
+
48
+ _length -- ;
49
+ }
50
+
51
+ /// <summary>
52
+ /// Gets or sets a polynomial term at the specified index.
53
+ /// </summary>
54
+ public PolynomItem this [ int index ]
55
+ {
56
+ get {
57
+ if ( index < 0 || index >= _length )
58
+ throw new IndexOutOfRangeException ( ) ;
59
+ return _polyItems [ index ] ;
60
+ }
61
+ set {
62
+ if ( index < 0 || index >= _length )
63
+ throw new IndexOutOfRangeException ( ) ;
64
+ _polyItems [ index ] = value ;
65
+ }
66
+ }
67
+
68
+ /// <summary>
69
+ /// Gets the number of polynomial terms in the polynomial.
70
+ /// </summary>
71
+ public int Count => _length ;
72
+
73
+ /// <summary>
74
+ /// Removes all polynomial terms from the polynomial.
75
+ /// </summary>
76
+ public void Clear ( )
77
+ {
78
+ _length = 0 ;
79
+ }
80
+
81
+ /// <summary>
82
+ /// Clones the polynomial, creating a new instance with the same polynomial terms.
83
+ /// </summary>
84
+ public Polynom Clone ( )
85
+ {
86
+ var newPolynom = new Polynom ( _length ) ;
87
+ Array . Copy ( _polyItems , newPolynom . _polyItems , _length ) ;
88
+ newPolynom . _length = _length ;
89
+ return newPolynom ;
20
90
}
21
91
22
92
/// <summary>
23
- /// Gets or sets the list of polynomial items, where each item represents a term in the polynomial .
93
+ /// Sorts the collection of <see cref="PolynomItem"/> using a custom comparer function .
24
94
/// </summary>
25
- public List < PolynomItem > PolyItems { get ; set ; }
95
+ /// <param name="comparer">
96
+ /// A function that compares two <see cref="PolynomItem"/> objects and returns an integer indicating their relative order:
97
+ /// less than zero if the first is less than the second, zero if they are equal, or greater than zero if the first is greater than the second.
98
+ /// </param>
99
+ public void Sort ( Func < PolynomItem , PolynomItem , int > comparer )
100
+ {
101
+ if ( comparer == null ) throw new ArgumentNullException ( nameof ( comparer ) ) ;
102
+
103
+ // Assuming you have a list or array to sort within your class
104
+ var items = _polyItems ;
105
+ if ( items == null || _length <= 1 )
106
+ {
107
+ return ; // Nothing to sort if the list is empty or contains only one element
108
+ }
109
+
110
+ void QuickSort ( int left , int right )
111
+ {
112
+ int i = left ;
113
+ int j = right ;
114
+ PolynomItem pivot = items [ ( left + right ) / 2 ] ;
115
+
116
+ while ( i <= j )
117
+ {
118
+ while ( comparer ( items [ i ] , pivot ) < 0 ) i ++ ;
119
+ while ( comparer ( items [ j ] , pivot ) > 0 ) j -- ;
120
+
121
+ if ( i <= j )
122
+ {
123
+ // Swap items[i] and items[j]
124
+ PolynomItem temp = items [ i ] ;
125
+ items [ i ] = items [ j ] ;
126
+ items [ j ] = temp ;
127
+ i ++ ;
128
+ j -- ;
129
+ }
130
+ }
131
+
132
+ // Recursively sort the sub-arrays
133
+ if ( left < j ) QuickSort ( left , j ) ;
134
+ if ( i < right ) QuickSort ( i , right ) ;
135
+ }
136
+
137
+ QuickSort ( 0 , _length - 1 ) ;
138
+ }
26
139
27
140
/// <summary>
28
141
/// Returns a string that represents the polynomial in standard algebraic notation.
@@ -32,7 +145,7 @@ public override string ToString()
32
145
{
33
146
var sb = new StringBuilder ( ) ;
34
147
35
- foreach ( var polyItem in this . PolyItems )
148
+ foreach ( var polyItem in _polyItems )
36
149
{
37
150
sb . Append ( "a^" + polyItem . Coefficient + "*x^" + polyItem . Exponent + " + " ) ;
38
151
}
@@ -43,6 +156,134 @@ public override string ToString()
43
156
44
157
return sb . ToString ( ) ;
45
158
}
159
+
160
+ /// <inheritdoc/>
161
+ public void Dispose ( )
162
+ {
163
+ Free ( _polyItems ) ;
164
+ _polyItems = null ;
165
+ }
166
+
167
+ /// <summary>
168
+ /// Ensures that the polynomial has enough capacity to store the specified number of polynomial terms.
169
+ /// </summary>
170
+ private void EnsureCapacity ( int min )
171
+ {
172
+ if ( _polyItems . Length < min )
173
+ {
174
+ // All math by QRCoder should be done with fixed polynomials, so we don't need to grow the capacity.
175
+ ThrowNotSupportedException ( ) ;
176
+
177
+ // Sample code for growing the capacity:
178
+ //var newArray = Allocate(Math.Max(min - 1, 8) * 2); // Grow by 2x, but at least by 8
179
+ //Array.Copy(_polyItems, newArray, _length);
180
+ //Free(_polyItems);
181
+ //_polyItems = newArray;
182
+ }
183
+
184
+ void ThrowNotSupportedException ( )
185
+ {
186
+ throw new NotSupportedException ( "The polynomial capacity is fixed and cannot be increased." ) ;
187
+ }
188
+ }
189
+
190
+ #if NETCOREAPP
191
+ /// <summary>
192
+ /// Allocates memory for the polynomial terms.
193
+ /// </summary>
194
+ private static PolynomItem [ ] Allocate ( int count )
195
+ {
196
+ return System . Buffers . ArrayPool < PolynomItem > . Shared . Rent ( count ) ;
197
+ }
198
+
199
+ /// <summary>
200
+ /// Frees memory allocated for the polynomial terms.
201
+ /// </summary>
202
+ private static void Free ( PolynomItem [ ] array )
203
+ {
204
+ System . Buffers . ArrayPool < PolynomItem > . Shared . Return ( array ) ;
205
+ }
206
+ #else
207
+ // Implement a poor-man's array pool for .NET Framework
208
+ [ ThreadStatic ]
209
+ private static List < PolynomItem [ ] > _arrayPool ;
210
+
211
+ /// <summary>
212
+ /// Allocates memory for the polynomial terms.
213
+ /// </summary>
214
+ private static PolynomItem [ ] Allocate ( int count )
215
+ {
216
+ if ( count <= 0 )
217
+ ThrowArgumentOutOfRangeException ( ) ;
218
+
219
+ // Search for a suitable array in the thread-local pool, if it has been initialized
220
+ if ( _arrayPool != null )
221
+ {
222
+ for ( int i = 0 ; i < _arrayPool . Count ; i ++ )
223
+ {
224
+ var array = _arrayPool [ i ] ;
225
+ if ( array . Length >= count )
226
+ {
227
+ _arrayPool . RemoveAt ( i ) ;
228
+ return array ;
229
+ }
230
+ }
231
+ }
232
+
233
+ // No suitable buffer found; create a new one
234
+ return new PolynomItem [ count ] ;
235
+
236
+ void ThrowArgumentOutOfRangeException ( )
237
+ {
238
+ throw new ArgumentOutOfRangeException ( nameof ( count ) , "The count must be a positive number." ) ;
239
+ }
240
+ }
241
+
242
+ /// <summary>
243
+ /// Frees memory allocated for the polynomial terms.
244
+ /// </summary>
245
+ private static void Free ( PolynomItem [ ] array )
246
+ {
247
+ if ( array == null )
248
+ ThrowArgumentNullException ( ) ;
249
+
250
+ // Initialize the thread-local pool if it's not already done
251
+ if ( _arrayPool == null )
252
+ _arrayPool = new List < PolynomItem [ ] > ( 8 ) ;
253
+
254
+ // Add the buffer back to the pool
255
+ _arrayPool . Add ( array ) ;
256
+
257
+ void ThrowArgumentNullException ( )
258
+ {
259
+ throw new ArgumentNullException ( nameof ( array ) ) ;
260
+ }
261
+ }
262
+ #endif
263
+
264
+ /// <summary>
265
+ /// Returns an enumerator that iterates through the polynomial terms.
266
+ /// </summary>
267
+ public PolynumEnumerator GetEnumerator ( ) => new PolynumEnumerator ( this ) ;
268
+
269
+ /// <summary>
270
+ /// Value type enumerator for the <see cref="Polynom"/> struct.
271
+ /// </summary>
272
+ public struct PolynumEnumerator
273
+ {
274
+ private Polynom _polynom ;
275
+ private int _index ;
276
+
277
+ public PolynumEnumerator ( Polynom polynom )
278
+ {
279
+ _polynom = polynom ;
280
+ _index = - 1 ;
281
+ }
282
+
283
+ public PolynomItem Current => _polynom [ _index ] ;
284
+
285
+ public bool MoveNext ( ) => ++ _index < _polynom . _length ;
286
+ }
46
287
}
47
288
}
48
289
}
0 commit comments