@@ -351,12 +351,18 @@ public BigInteger(byte[] val, int off, int len) {
351
351
throw new NumberFormatException ("Zero length BigInteger" );
352
352
}
353
353
Objects .checkFromIndexSize (off , len , val .length );
354
+ if (len == 0 ) {
355
+ mag = ZERO .mag ;
356
+ signum = ZERO .signum ;
357
+ return ;
358
+ }
354
359
355
- if (val [off ] < 0 ) {
356
- mag = makePositive (val , off , len );
360
+ int b = val [off ];
361
+ if (b < 0 ) {
362
+ mag = makePositive (b , val , off , len );
357
363
signum = -1 ;
358
364
} else {
359
- mag = stripLeadingZeroBytes (val , off , len );
365
+ mag = stripLeadingZeroBytes (b , val , off , len );
360
366
signum = (mag .length == 0 ? 0 : 1 );
361
367
}
362
368
if (mag .length >= MAX_MAG_LENGTH ) {
@@ -4604,77 +4610,167 @@ private static int[] trustedStripLeadingZeroInts(int[] val) {
4604
4610
return keep == 0 ? val : java .util .Arrays .copyOfRange (val , keep , vlen );
4605
4611
}
4606
4612
4607
- /**
4613
+ private static int [] stripLeadingZeroBytes (byte [] a , int from , int len ) {
4614
+ return stripLeadingZeroBytes (Integer .MIN_VALUE , a , from , len );
4615
+ }
4616
+
4617
+ /*
4608
4618
* Returns a copy of the input array stripped of any leading zero bytes.
4619
+ * The returned array is either empty, or its 0-th element is non-zero,
4620
+ * meeting the "minimal" requirement for field mag (see comment on mag).
4621
+ *
4622
+ * The range [from, from + len) must be well-formed w.r.t. array a.
4623
+ *
4624
+ * b < -128 means that a[from] has not yet been read.
4625
+ * Otherwise, b must be a[from], have been read only once before invoking
4626
+ * this method, and len > 0 must hold.
4609
4627
*/
4610
- private static int [] stripLeadingZeroBytes (byte [] a , int off , int len ) {
4611
- int indexBound = off + len ;
4612
- int keep ;
4613
-
4614
- // Find first nonzero byte
4615
- for (keep = off ; keep < indexBound && a [keep ] == 0 ; keep ++)
4616
- ;
4617
-
4618
- // Allocate new array and copy relevant part of input array
4619
- int intLength = ((indexBound - keep ) + 3 ) >>> 2 ;
4620
- int [] result = new int [intLength ];
4621
- int b = indexBound - 1 ;
4622
- for (int i = intLength -1 ; i >= 0 ; i --) {
4623
- result [i ] = a [b --] & 0xff ;
4624
- int bytesRemaining = b - keep + 1 ;
4625
- int bytesToTransfer = Math .min (3 , bytesRemaining );
4626
- for (int j =8 ; j <= (bytesToTransfer << 3 ); j += 8 )
4627
- result [i ] |= ((a [b --] & 0xff ) << j );
4628
+ private static int [] stripLeadingZeroBytes (int b , byte [] a , int from , int len ) {
4629
+ /*
4630
+ * Except for the first byte, each read access to the input array a
4631
+ * is of the form a[from++].
4632
+ * The index from is never otherwise altered, except right below,
4633
+ * and only increases in steps of 1, always up to index to.
4634
+ * Hence, each byte in the array is read exactly once, from lower to
4635
+ * higher indices (from most to least significant byte).
4636
+ */
4637
+ if (len == 0 ) {
4638
+ return ZERO .mag ;
4628
4639
}
4629
- return result ;
4640
+ int to = from + len ;
4641
+ if (b < -128 ) {
4642
+ b = a [from ];
4643
+ }
4644
+ /* Either way, a[from] has now been read exactly once, skip to next. */
4645
+ ++from ;
4646
+ /*
4647
+ * Set up the shortest int[] for the sequence of the bytes
4648
+ * b, a[from+1], ..., a[to-1] (len > 0)
4649
+ * Shortest means first skipping leading zeros.
4650
+ */
4651
+ for (; b == 0 && from < to ; b = a [from ++])
4652
+ ; //empty body
4653
+ if (b == 0 ) {
4654
+ /* Here, from == to as well. All bytes are zeros. */
4655
+ return ZERO .mag ;
4656
+ }
4657
+ /*
4658
+ * Allocate just enough ints to hold (to - from + 1) bytes, that is
4659
+ * ((to - from + 1) + 3) / 4 = (to - from) / 4 + 1
4660
+ */
4661
+ int [] res = new int [((to - from ) >> 2 ) + 1 ];
4662
+ /*
4663
+ * A "digit" is a group of 4 adjacent bytes aligned w.r.t. index to.
4664
+ * (Implied 0 bytes are prepended as needed.)
4665
+ * b is the most significant byte not 0.
4666
+ * Digit d0 spans the range of indices that includes current (from - 1).
4667
+ */
4668
+ int d0 = b & 0xFF ;
4669
+ while (((to - from ) & 0x3 ) != 0 ) {
4670
+ d0 = d0 << 8 | a [from ++] & 0xFF ;
4671
+ }
4672
+ res [0 ] = d0 ;
4673
+ /*
4674
+ * Prepare the remaining digits.
4675
+ * (to - from) is a multiple of 4, so prepare an int for every 4 bytes.
4676
+ * This is a candidate for Unsafe.copy[Swap]Memory().
4677
+ */
4678
+ int i = 1 ;
4679
+ while (from < to ) {
4680
+ res [i ++] = a [from ++] << 24 | (a [from ++] & 0xFF ) << 16
4681
+ | (a [from ++] & 0xFF ) << 8 | (a [from ++] & 0xFF );
4682
+ }
4683
+ return res ;
4630
4684
}
4631
4685
4632
- /**
4686
+ /*
4633
4687
* Takes an array a representing a negative 2's-complement number and
4634
4688
* returns the minimal (no leading zero bytes) unsigned whose value is -a.
4689
+ *
4690
+ * len > 0 must hold.
4691
+ * The range [from, from + len) must be well-formed w.r.t. array a.
4692
+ * b is assumed to be the result of reading a[from] and to meet b < 0.
4635
4693
*/
4636
- private static int [] makePositive (byte [] a , int off , int len ) {
4637
- int keep , k ;
4638
- int indexBound = off + len ;
4639
-
4640
- // Find first non-sign (0xff) byte of input
4641
- for (keep =off ; keep < indexBound && a [keep ] == -1 ; keep ++)
4642
- ;
4643
-
4644
-
4645
- /* Allocate output array. If all non-sign bytes are 0x00, we must
4646
- * allocate space for one extra output byte. */
4647
- for (k =keep ; k < indexBound && a [k ] == 0 ; k ++)
4648
- ;
4649
-
4650
- int extraByte = (k == indexBound ) ? 1 : 0 ;
4651
- int intLength = ((indexBound - keep + extraByte ) + 3 ) >>> 2 ;
4652
- int result [] = new int [intLength ];
4653
-
4654
- /* Copy one's complement of input into output, leaving extra
4655
- * byte (if it exists) == 0x00 */
4656
- int b = indexBound - 1 ;
4657
- for (int i = intLength -1 ; i >= 0 ; i --) {
4658
- result [i ] = a [b --] & 0xff ;
4659
- int numBytesToTransfer = Math .min (3 , b -keep +1 );
4660
- if (numBytesToTransfer < 0 )
4661
- numBytesToTransfer = 0 ;
4662
- for (int j =8 ; j <= 8 *numBytesToTransfer ; j += 8 )
4663
- result [i ] |= ((a [b --] & 0xff ) << j );
4664
-
4665
- // Mask indicates which bits must be complemented
4666
- int mask = -1 >>> (8 *(3 -numBytesToTransfer ));
4667
- result [i ] = ~result [i ] & mask ;
4694
+ private static int [] makePositive (int b , byte [] a , int from , int len ) {
4695
+ /*
4696
+ * By assumption, b == a[from] < 0 and len > 0.
4697
+ *
4698
+ * First collect the bytes into the resulting array res.
4699
+ * Then convert res to two's complement.
4700
+ *
4701
+ * Except for b == a[from], each read access to the input array a
4702
+ * is of the form a[from++].
4703
+ * The index from is never otherwise altered, except right below,
4704
+ * and only increases in steps of 1, always up to index to.
4705
+ * Hence, each byte in the array is read exactly once, from lower to
4706
+ * higher indices (from most to least significant byte).
4707
+ */
4708
+ int to = from + len ;
4709
+ /* b == a[from] has been read exactly once, skip to next index. */
4710
+ ++from ;
4711
+ /* Skip leading -1 bytes. */
4712
+ for (; b == -1 && from < to ; b = a [from ++])
4713
+ ; //empty body
4714
+ /*
4715
+ * A "digit" is a group of 4 adjacent bytes aligned w.r.t. index to.
4716
+ * b is the most significant byte not -1, or -1 only if from == to.
4717
+ * Digit d0 spans the range of indices that includes current (from - 1).
4718
+ * (Implied -1 bytes are prepended to array a as needed.)
4719
+ * It usually corresponds to res[0], except for the special case below.
4720
+ */
4721
+ int d0 = -1 << 8 | b & 0xFF ;
4722
+ while (((to - from ) & 0x3 ) != 0 ) {
4723
+ d0 = d0 << 8 | (b = a [from ++]) & 0xFF ;
4724
+ }
4725
+ int f = from ; // keeps the current from for sizing purposes later
4726
+ /* Skip zeros adjacent to d0, if at all. */
4727
+ for (; b == 0 && from < to ; b = a [from ++])
4728
+ ; //empty body
4729
+ /*
4730
+ * b is the most significant non-zero byte at or after (f - 1),
4731
+ * or 0 only if from == to.
4732
+ * Digit d spans the range of indices that includes (f - 1).
4733
+ */
4734
+ int d = b & 0xFF ;
4735
+ while (((to - from ) & 0x3 ) != 0 ) {
4736
+ d = d << 8 | a [from ++] & 0xFF ;
4668
4737
}
4669
-
4670
- // Add one to one's complement to generate two's complement
4671
- for (int i =result .length -1 ; i >= 0 ; i --) {
4672
- result [i ] = (int )((result [i ] & LONG_MASK ) + 1 );
4673
- if (result [i ] != 0 )
4674
- break ;
4738
+ /*
4739
+ * If the situation here is like this:
4740
+ * index: f to == from
4741
+ * ..., -1,-1, 0,0,0,0, 0,0,0,0, ..., 0,0,0,0
4742
+ * digit: d0 d
4743
+ * then, as shown, the number of zeros is a positive multiple of 4.
4744
+ * The array res needs a minimal length of (1 + 1 + (to - f) / 4)
4745
+ * to accommodate the two's complement, including a leading 1.
4746
+ * In any other case, there is at least one byte that is non-zero.
4747
+ * The array for the two's complement has length (0 + 1 + (to - f) / 4).
4748
+ * c is 1, resp., 0 for the two situations.
4749
+ */
4750
+ int c = (to - from | d0 | d ) == 0 ? 1 : 0 ;
4751
+ int [] res = new int [c + 1 + ((to - f ) >> 2 )];
4752
+ res [0 ] = c == 0 ? d0 : -1 ;
4753
+ int i = res .length - ((to - from ) >> 2 );
4754
+ if (i > 1 ) {
4755
+ res [i - 1 ] = d ;
4675
4756
}
4676
-
4677
- return result ;
4757
+ /*
4758
+ * Prepare the remaining digits.
4759
+ * (to - from) is a multiple of 4, so prepare an int for every 4 bytes.
4760
+ * This is a candidate for Unsafe.copy[Swap]Memory().
4761
+ */
4762
+ while (from < to ) {
4763
+ res [i ++] = a [from ++] << 24 | (a [from ++] & 0xFF ) << 16
4764
+ | (a [from ++] & 0xFF ) << 8 | (a [from ++] & 0xFF );
4765
+ }
4766
+ /* Convert to two's complement. Here, i == res.length */
4767
+ while (--i >= 0 && res [i ] == 0 )
4768
+ ; // empty body
4769
+ res [i ] = -res [i ];
4770
+ while (--i >= 0 ) {
4771
+ res [i ] = ~res [i ];
4772
+ }
4773
+ return res ;
4678
4774
}
4679
4775
4680
4776
/**
0 commit comments