@@ -510,6 +510,7 @@ private static bool NumberToBigInteger(ref BigNumberBuffer number, out BigIntege
510
510
int currentBufferSize = 0 ;
511
511
512
512
int [ ] ? arrayFromPool = null ;
513
+ int [ ] ? rentedBuffer = null ;
513
514
514
515
int totalDigitCount = 0 ;
515
516
int numberScale = number . scale ;
@@ -607,11 +608,24 @@ bool ProcessChunk(ReadOnlySpan<char> chunkDigits, ref Span<uint> currentBuffer)
607
608
int bufferSize = ( totalDigitCount + MaxPartialDigits - 1 ) / MaxPartialDigits ;
608
609
609
610
Span < uint > buffer = new uint [ bufferSize ] ;
611
+ rentedBuffer = ArrayPool < int > . Shared . Rent ( bufferSize ) ;
612
+ Span < uint > newBuffer = MemoryMarshal . Cast < int , uint > ( rentedBuffer ) ;
613
+ newBuffer . Clear ( ) ;
614
+
615
+ // To ensure finally stored in newBuffer is the borrowed buffer.
616
+ int blockSize = 1 ;
617
+ do
618
+ {
619
+ Span < uint > tmp = buffer ;
620
+ buffer = newBuffer ;
621
+ newBuffer = tmp ;
622
+ blockSize *= 2 ;
623
+ } while ( blockSize < bufferSize ) ;
610
624
611
625
// Separate every MaxPartialDigits digits and store them in the buffer.
612
626
// Buffers are treated as little-endian. That means, the array { 234567890, 1 }
613
627
// represents the number 1234567890.
614
- int bufferIndex = buffer . Length - 1 ;
628
+ int bufferIndex = bufferSize - 1 ;
615
629
uint currentBlock = 0 ;
616
630
int shiftUntil = ( totalDigitCount - 1 ) % MaxPartialDigits ;
617
631
int remainingIntDigitCount = totalDigitCount ;
@@ -658,13 +672,11 @@ bool ProcessChunk(ReadOnlySpan<char> chunkDigits, ref Span<uint> currentBuffer)
658
672
659
673
unsafe
660
674
{
661
- Span < uint > newBuffer = new uint [ bufferSize ] ;
662
-
663
675
arrayFromPool = ArrayPool < int > . Shared . Rent ( 1 ) ;
664
676
Span < uint > multiplier = MemoryMarshal . Cast < int , uint > ( arrayFromPool ) ;
665
677
multiplier [ 0 ] = TenPowMaxPartial ;
666
678
667
- int blockSize = 1 ;
679
+ blockSize = 1 ;
668
680
while ( true )
669
681
{
670
682
fixed ( uint * bufPtr = buffer , newBufPtr = newBuffer , mulPtr = multiplier )
@@ -739,6 +751,8 @@ bool ProcessChunk(ReadOnlySpan<char> chunkDigits, ref Span<uint> currentBuffer)
739
751
}
740
752
}
741
753
754
+ Debug . Assert ( MemoryMarshal . Cast < int , uint > ( rentedBuffer ) == newBuffer ) ;
755
+
742
756
// shrink buffer to the currently used portion.
743
757
// First, calculate the rough size of the buffer from the ratio that the number
744
758
// of digits follows. Then, shrink the size until there is no more space left.
@@ -794,6 +808,10 @@ bool ProcessChunk(ReadOnlySpan<char> chunkDigits, ref Span<uint> currentBuffer)
794
808
{
795
809
ArrayPool < int > . Shared . Return ( arrayFromPool ) ;
796
810
}
811
+ if ( rentedBuffer != null )
812
+ {
813
+ ArrayPool < int > . Shared . Return ( rentedBuffer ) ;
814
+ }
797
815
}
798
816
799
817
void MultiplyAdd ( ref Span < uint > currentBuffer , uint multiplier , uint addValue )
0 commit comments