11using System ;
22using System . Collections . Generic ;
33using System . Diagnostics . CodeAnalysis ;
4- using System . Reflection ;
54using System . Runtime . CompilerServices ;
6- using System . Runtime . InteropServices ;
7-
8-
9-
105
116#if ! NETSTANDARD2_0
127using System . Runtime . Intrinsics ;
@@ -37,7 +32,9 @@ public unsafe class CmSketchCore<T, I>
3732 private const long OneMask = 0x1111111111111111L ;
3833
3934 private long [ ] table ;
35+ #if NET6_0_OR_GREATER
4036 private long * tableAddr ;
37+ #endif
4138 private int sampleSize ;
4239 private int blockMask ;
4340 private int size ;
@@ -117,13 +114,7 @@ public void Increment(T value)
117114 /// </summary>
118115 public void Clear ( )
119116 {
120- #if NET6_0_OR_GREATER
121- table = GC . AllocateArray < long > ( table . Length , true ) ;
122- long pointer = ( long ) Unsafe . AsPointer ( ref table [ 0 ] ) ;
123- tableAddr = ( long * ) pointer + pointer % 32 ;
124- #else
125- table = new long [ table . Length ] ;
126- #endif
117+ Array . Clear ( table , 0 , table . Length ) ;
127118 size = 0 ;
128119 }
129120
@@ -132,15 +123,17 @@ private void EnsureCapacity(long maximumSize)
132123 {
133124 int maximum = ( int ) Math . Min ( maximumSize , int . MaxValue >> 1 ) ;
134125
135- #if NET6_0_OR_GREATER
136- // over alloc by 4 to give 32 byte buffer
137- table = GC . AllocateArray < long > ( Math . Max ( BitOps . CeilingPowerOfTwo ( maximum ) , 8 ) + 4 , true ) ;
126+ #if NET6_0_OR_GREATER
127+ // over alloc by 4 to give 32 bytes padding, tableAddr is then aligned to 32 bytes
128+ const int buffer = 4 ;
129+ table = GC . AllocateArray < long > ( Math . Max ( BitOps . CeilingPowerOfTwo ( maximum ) , 8 ) + buffer , true ) ;
138130 long pointer = ( long ) Unsafe . AsPointer ( ref table [ 0 ] ) ;
139131 tableAddr = ( long * ) pointer + pointer % 32 ;
140- #else
132+ blockMask = ( int ) ( ( uint ) ( table . Length - buffer ) >> 3 ) - 1 ;
133+ #else
141134 table = new long [ Math . Max ( BitOps . CeilingPowerOfTwo ( maximum ) , 8 ) ] ;
142- #endif
143- blockMask = ( int ) ( ( uint ) ( table . Length - 4 ) >> 3 ) - 1 ;
135+ blockMask = ( int ) ( ( uint ) ( table . Length ) >> 3 ) - 1 ;
136+ #endif
144137 sampleSize = ( maximumSize == 0 ) ? 10 : ( 10 * maximum ) ;
145138
146139 size = 0 ;
@@ -265,7 +258,11 @@ private unsafe int EstimateFrequencyAvx(T value)
265258 Vector128 < int > blockOffset = Avx2 . Add ( Vector128 . Create ( block ) , offset ) ; // i - table index
266259 blockOffset = Avx2 . Add ( blockOffset , Vector128 . Create ( 0 , 2 , 4 , 6 ) ) ; // + (i << 1)
267260
261+ #if NET6_0_OR_GREATER
268262 long * tablePtr = tableAddr ;
263+ #else
264+ fixed ( long * tablePtr = table )
265+ #endif
269266 {
270267 Vector256 < long > tableVector = Avx2 . GatherVector256 ( tablePtr , blockOffset , 8 ) ;
271268 index = Avx2 . ShiftLeftLogical ( index , 2 ) ;
@@ -283,7 +280,7 @@ private unsafe int EstimateFrequencyAvx(T value)
283280 . AsUInt16 ( ) ;
284281
285282 // set the zeroed high parts of the long value to ushort.Max
286- #if NET6_0
283+ #if NET6_0_OR_GREATER
287284 count = Avx2 . Blend ( count , Vector128 < ushort > . AllBitsSet , 0b10101010 ) ;
288285#else
289286 count = Avx2 . Blend ( count , Vector128 . Create ( ushort . MaxValue ) , 0b10101010 ) ;
@@ -308,8 +305,11 @@ private unsafe void IncrementAvx(T value)
308305 Vector128 < int > blockOffset = Avx2 . Add ( Vector128 . Create ( block ) , offset ) ; // i - table index
309306 blockOffset = Avx2 . Add ( blockOffset , Vector128 . Create ( 0 , 2 , 4 , 6 ) ) ; // + (i << 1)
310307
311- //fixed (long* tablePtr = table)
312- long * tablePtr = tableAddr ;
308+ #if NET6_0_OR_GREATER
309+ long * tablePtr = tableAddr ;
310+ #else
311+ fixed ( long * tablePtr = table )
312+ #endif
313313 {
314314 Vector256 < long > tableVector = Avx2 . GatherVector256 ( tablePtr , blockOffset , 8 ) ;
315315
0 commit comments