exponentAdjust = 4*(leftDigits - 1); } else { // Cases 3 and 4 exponentAdjust = -4*( rightDigits - signifLength + 1); } // If the significand is zero, the exponent doesn't // matter; return a properly signed zero. if (signifLength == 0) { // Only zeros in input return new FloatingDecimal(sign * 0.0); } } // Extract Exponent /* * Use an int to read in the exponent value; this should * provide more than sufficient range for non-contrived * inputs. If reading the exponent in as an int does * overflow, examine the sign of the exponent and * significand to determine what to do. */ String group8 = m.group(8); boolean positiveExponent = ( group8 == null ) || group8.equals("+"); long unsignedRawExponent; try { unsignedRawExponent = Integer.parseInt(m.group(9)); } catch (NumberFormatException e) { // At this point, we know the exponent is // syntactically well-formed as a sequence of // digits. Therefore, if an NumberFormatException // is thrown, it must be due to overflowing int's // range. Also, at this point, we have already // checked for a zero significand. Thus the signs // of the exponent and significand determine the // final result: // // significand // + - // exponent + +infinity -infinity // - +0.0 -0.0 return new FloatingDecimal(sign * (positiveExponent ? Double.POSITIVE_INFINITY : 0.0)); } long rawExponent = (positiveExponent ? 1L : -1L) * // exponent sign unsignedRawExponent; // exponent magnitude // Calculate partially adjusted exponent long exponent = rawExponent + exponentAdjust ; // Starting copying non-zero bits into proper position in // a long; copy explicit bit too; this will be masked // later for normal values. boolean round = false; boolean sticky = false; int bitsCopied=0; int nextShift=0; long significand=0L; // First iteration is different, since we only copy // from the leading significand bit; one more exponent // adjust will be needed... // IMPORTANT: make leadingDigit a long to avoid // surprising shift semantics! long leadingDigit = getHexDigit(significandString, 0); /* * Left shift the leading digit (53 - (bit position of * leading 1 in digit)); this sets the top bit of the * significand to 1. The nextShift value is adjusted * to take into account the number of bit positions of * the leadingDigit actually used. Finally, the * exponent is adjusted to normalize the significand * as a binary value, not just a hex value. */ if (leadingDigit == 1) { significand |= leadingDigit << 52; nextShift = 52 - 4; /* exponent += 0 */ } else if (leadingDigit <= 3) { // [2, 3] significand |= leadingDigit << 51; nextShift = 52 - 5; exponent += 1; } else if (leadingDigit <= 7) { // [4, 7] significand |= leadingDigit << 50; nextShift = 52 - 6; exponent += 2; } else if (leadingDigit <= 15) { // [8, f] significand |= leadingDigit << 49; nextShift = 52 - 7; exponent += 3; } else { throw new AssertionError("Result from digit conversion too large!"); } // The preceding if-else could be replaced by a single // code block based on the high-order bit set in // leadingDigit. Given leadingOnePosition, // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition); // nextShift = 52 - (3 + leadingOnePosition); // exponent += (leadingOnePosition-1); /* * Now the exponent variable is equal to the normalized * binary exponent. Code below will make representation * adjustments if the exponent is incremented after * rounding (includes overflows to infinity) or if the * result is subnormal. */ // Copy digit into significand until the significand can't // hold another full hex digit or there are no more input // hex digits. int i = 0; for(i = 1; i < signifLength && nextShift >= 0; i++) { long currentDigit = getHexDigit(significandString, i); significand |= (currentDigit << nextShift); nextShift-=4; } // After the above loop, the bulk of the string is copied. // Now, we must copy any partial hex digits into the // significand AND compute the round bit and start computing // sticky bit. if ( i < signifLength ) { // at least one hex input digit exists long currentDigit = getHexDigit(significandString, i); // from nextShift, figure out how many bits need // to be copied, if any switch(nextShift) { // must be negative case -1: // three bits need to be copied in; can // set round bit significand |= ((currentDigit & 0xEL) >> 1); round = (currentDigit & 0x1L) != 0L; break; case -2: // two bits need to be copied in; can // set round and start sticky significand |= ((currentDigit & 0xCL) >> 2); round = (currentDigit &0x2L) != 0L; sticky = (currentDigit & 0x1L) != 0; break; case -3: // one bit needs to be copied in significand |= ((currentDigit & 0x8L)>>3); // Now set round and start sticky, if possible round = (currentDigit &0x4L) != 0L; sticky = (currentDigit & 0x3L) != 0; break; case -4: // all bits copied into significand; set // round and start sticky round = ((currentDigit & 0x8L) != 0); // is top bit set? // nonzeros in three low order bits? sticky = (currentDigit & 0x7L) != 0; break; default: throw new AssertionError("Unexpected shift distance remainder."); // break; } // Round is set; sticky might be set. // For the sticky bit, it suffices to check the // current digit and test for any nonzero digits in // the remaining unprocessed input. i++; while(i < signifLength && !sticky) { currentDigit = getHexDigit(significandString,i); sticky = sticky || (currentDigit != 0); i++; } } // else all of string was seen, round and sticky are // correct as false. // Check for overflow and update exponent accordingly. if (exponent > DoubleConsts.MAX_EXPONENT) { // Infinite result // overflow to properly signed infinity return new FloatingDecimal(sign * Double.POSITIVE_INFINITY); } else { // Finite return value if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result exponent >= DoubleConsts.MIN_EXPONENT) { // The result returned in this block cannot be a // zero or subnormal; however after the // significand is adjusted from rounding, we could // still overflow in infinity. // AND exponent bits into significand; if the // significand is incremented and overflows from // rounding, this combination will update the // exponent correctly, even in the case of // Double.MAX_VALUE overflowing to infinity. significand = (( ((long)exponent + (long)DoubleConsts.EXP_BIAS) << (DoubleConsts.SIGNIFICAND_WIDTH-1)) & DoubleConsts.EXP_BIT_MASK) | (DoubleConsts.SIGNIF_BIT_MASK & significand); } else { // Subnormal or zero // (exponent < DoubleConsts.MIN_EXPONENT) if (exponent < (DoubleConsts.MIN_SUB_EXPONENT -1 )) { // No way to round back to nonzero value // regardless of significand if the exponent is // less than -1075. return new FloatingDecimal(sign * 0.0); } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023 /* * Find bit position to round to; recompute * round and sticky bits, and shift * significand right appropriately. */ sticky = sticky || round; round = false; // Number of bits of significand to preserve is // exponent - abs_min_exp +1 // check: // -1075 +1074 + 1 = 0 // -1023 +1074 + 1 = 52 int bitsDiscarded = 53 - ((int)exponent - DoubleConsts.MIN_SUB_EXPONENT + 1); assert bitsDiscarded >= 1 && bitsDiscarded <= 53; // What to do here: // First, isolate the new round bit round = (significand & (1L << (bitsDiscarded -1))) != 0L; if (bitsDiscarded > 1) { // create mask to update sticky bits; low // order bitsDiscarded bits should be 1 long mask = ~((~0L) << (bitsDiscarded -1)); sticky = sticky || ((significand & mask) != 0L ) ; } // Now, discard the bits significand = significand >> bitsDiscarded; significand = (( ((long)(DoubleConsts.MIN_EXPONENT -1) + // subnorm exp. (long)DoubleConsts.EXP_BIAS) << (DoubleConsts.SIGNIFICAND_WIDTH-1)) & DoubleConsts.EXP_BIT_MASK) | (DoubleConsts.SIGNIF_BIT_MASK & significand); } } // The significand variable now contains the currently // appropriate exponent bits too. /* * Determine if significand should be incremented; * making this determination depends on the least * significant bit and the round and sticky bits. * * Round to nearest even rounding table, adapted from * table 4.7 in "Computer Arithmetic" by IsraelKoren. * The digit to the left of the "decimal" point is the * least significant bit, the digits to the right of * the point are the round and sticky bits * * Number Round(x) * x0.00 x0. * x0.01 x0. * x0.10 x0. * x0.11 x1. = x0. +1 * x1.00 x1. * x1.01 x1. * x1.10 x1. + 1 * x1.11 x1. + 1 */ boolean incremented = false; boolean leastZero = ((significand & 1L) == 0L); if( ( leastZero && round && sticky ) || ((!leastZero) && round )) { incremented = true; significand++; } FloatingDecimal fd = new FloatingDecimal(FpUtils.rawCopySign( Double.longBitsToDouble(significand), sign)); /* * Set roundingDir variable field of fd properly so * that the input string can be properly rounded to a * float value. There are two cases to consider: * * 1. rounding to double discards sticky bit * information that would change the result of a float * rounding (near halfway case between two floats) * * 2. rounding to double rounds up when rounding up * would not occur when rounding to float. * * For former case only needs to be considered when * the bits rounded away when casting to float are all * zero; otherwise, float round bit is properly set * and sticky will already be true. * * The lower exponent bound for the code below is the * minimum (normalized) subnormal exponent - 1 since a * value with that exponent can round up to the * minimum subnormal value and the sticky bit * information must be preserved (i.e. case 1). */ if ((exponent >= FloatConsts.MIN_SUB_EXPONENT-1) && (exponent <= FloatConsts.MAX_EXPONENT ) ){ // Outside above exponent range, the float value // will be zero or infinity. /* * If the low-order 28 bits of a rounded double * significand are 0, the double could be a * half-way case for a rounding to float. If the * double value is a half-way case, the double * significand may have to be modified to round * the the right float value (see the stickyRound * method). If the rounding to double has lost * what would be float sticky bit information, the * double significand must be incremented. If the * double value's significand was itself * incremented, the float value may end up too * large so the increment should be undone. */ if ((significand & 0xfffffffL) == 0x0L) { // For negative values, the sign of the // roundDir is the same as for positive values // since adding 1 increasing the significand's // magnitude and subtracting 1 decreases the // significand's magnitude. If neither round // nor sticky is true, the double value is // exact and no adjustment is required for a // proper float rounding. if( round || sticky) { if (leastZero) { // prerounding lsb is 0 // If round and sticky were both true, // and the least significant // significand bit were 0, the rounded // significand would not have its // low-order bits be zero. Therefore, // we only need to adjust the // significand if round XOR sticky is // true. if (round ^ sticky) { fd.roundDir = 1; } } else { // prerounding lsb is 1 // If the prerounding lsb is 1 and the // resulting significand has its // low-order bits zero, the significand // was incremented. Here, we undo the // increment, which will ensure the // right guard and sticky bits for the // float rounding. if (round) fd.roundDir = -1; } } } } fd.fromHex = true; return fd; } } } /** * Return <code>s</code> with any leading zeros removed. */ static String stripLeadingZeros(String s) { return s.replaceFirst("^0+", ""); } /** * Extract a hexadecimal digit from position <code>position</code> * of string <code>s</code>. */ static int getHexDigit(String s, int position) { int value = Character.digit(s.charAt(position), 16); if (value <= -1 || value >= 16) { throw new AssertionError("Unexpected failure of digit conversion of " + s.charAt(position)); } return value; } } /* * A really, really simple bigint package * tailored to the needs of floating base conversion. */class FDBigInt { int nWords; // number of words used int data[]; // value: data[0] is least significant public FDBigInt( int v ){ nWords = 1; data = new int[1]; data[0] = v; } public FDBigInt( long v ){ data = new int[2]; data[0] = (int)v; data[1] = (int)(v>>>32); nWords = (data[1]==0) ? 1 : 2; } public FDBigInt( FDBigInt other ){ data = new int[nWords = other.nWords]; System.arraycopy( other.data, 0, data, 0, nWords ); } private FDBigInt( int [] d, int n ){ data = d; nWords = n; } public FDBigInt( long seed, char digit[], int nd0, int nd ){ int n= (nd+8)/9; // estimate size needed. if ( n < 2 ) n = 2; data = new int[n]; // allocate enough space data[0] = (int)seed; // starting value data[1] = (int)(seed>>>32); nWords = (data[1]==0) ? 1 : 2; int i = nd0; int limit = nd-5; // slurp digits 5 at a time. int v; while ( i < limit ){ int ilim = i+5; v = (int)digit[i++]-(int)'0'; while( i <ilim ){ v = 10*v + (int)digit[i++]-(int)'0'; } multaddMe( 100000, v); // ... where 100000 is 10^5. } int factor = 1; v = 0; while ( i < nd ){ v = 10*v + (int)digit[i++]-(int)'0'; factor *= 10; } if ( factor != 1 ){ multaddMe( factor, v ); } } /* * Left shift by c bits. * Shifts this in place. */ public void lshiftMe( int c )throws IllegalArgumentException { if ( c <= 0 ){ if ( c == 0 ) return; // silly. else throw new IllegalArgumentException("negative shift count"); } int wordcount = c>>5; int bitcount = c & 0x1f; int anticount = 32-bitcount; int t[] = data; int s[] = data; if ( nWords+wordcount+1 > t.length ){ // reallocate. t = new int[ nWords+wordcount+1 ]; } int target = nWords+wordcount; int src = nWords-1; if ( bitcount == 0 ){ // special hack, since an anticount of 32 won't go! System.arraycopy( s, 0, t, wordcount, nWords ); target = wordcount-1;Lines 2001–2500 of 2878. Previous lines Load more
exponentAdjust = 4*(leftDigits - 1); } else { // Cases 3 and 4 exponentAdjust = -4*( rightDigits - signifLength + 1); } // If the significand is zero, the exponent doesn't // matter; return a properly signed zero. if (signifLength == 0) { // Only zeros in input return new FloatingDecimal(sign * 0.0); } } // Extract Exponent /* * Use an int to read in the exponent value; this should * provide more than sufficient range for non-contrived * inputs. If reading the exponent in as an int does * overflow, examine the sign of the exponent and * significand to determine what to do. */ String group8 = m.group(8); boolean positiveExponent = ( group8 == null ) || group8.equals("+"); long unsignedRawExponent; try { unsignedRawExponent = Integer.parseInt(m.group(9)); } catch (NumberFormatException e) { // At this point, we know the exponent is // syntactically well-formed as a sequence of // digits. Therefore, if an NumberFormatException // is thrown, it must be due to overflowing int's // range. Also, at this point, we have already // checked for a zero significand. Thus the signs // of the exponent and significand determine the // final result: // // significand // + - // exponent + +infinity -infinity // - +0.0 -0.0 return new FloatingDecimal(sign * (positiveExponent ? Double.POSITIVE_INFINITY : 0.0)); } long rawExponent = (positiveExponent ? 1L : -1L) * // exponent sign unsignedRawExponent; // exponent magnitude // Calculate partially adjusted exponent long exponent = rawExponent + exponentAdjust ; // Starting copying non-zero bits into proper position in // a long; copy explicit bit too; this will be masked // later for normal values. boolean round = false; boolean sticky = false; int bitsCopied=0; int nextShift=0; long significand=0L; // First iteration is different, since we only copy // from the leading significand bit; one more exponent // adjust will be needed... // IMPORTANT: make leadingDigit a long to avoid // surprising shift semantics! long leadingDigit = getHexDigit(significandString, 0); /* * Left shift the leading digit (53 - (bit position of * leading 1 in digit)); this sets the top bit of the * significand to 1. The nextShift value is adjusted * to take into account the number of bit positions of * the leadingDigit actually used. Finally, the * exponent is adjusted to normalize the significand * as a binary value, not just a hex value. */ if (leadingDigit == 1) { significand |= leadingDigit << 52; nextShift = 52 - 4; /* exponent += 0 */ } else if (leadingDigit <= 3) { // [2, 3] significand |= leadingDigit << 51; nextShift = 52 - 5; exponent += 1; } else if (leadingDigit <= 7) { // [4, 7] significand |= leadingDigit << 50; nextShift = 52 - 6; exponent += 2; } else if (leadingDigit <= 15) { // [8, f] significand |= leadingDigit << 49; nextShift = 52 - 7; exponent += 3; } else { throw new AssertionError("Result from digit conversion too large!"); } // The preceding if-else could be replaced by a single // code block based on the high-order bit set in // leadingDigit. Given leadingOnePosition, // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition); // nextShift = 52 - (3 + leadingOnePosition); // exponent += (leadingOnePosition-1); /* * Now the exponent variable is equal to the normalized * binary exponent. Code below will make representation * adjustments if the exponent is incremented after * rounding (includes overflows to infinity) or if the * result is subnormal. */ // Copy digit into significand until the significand can't // hold another full hex digit or there are no more input // hex digits. int i = 0; for(i = 1; i < signifLength && nextShift >= 0; i++) { long currentDigit = getHexDigit(significandString, i); significand |= (currentDigit << nextShift); nextShift-=4; } // After the above loop, the bulk of the string is copied. // Now, we must copy any partial hex digits into the // significand AND compute the round bit and start computing // sticky bit. if ( i < signifLength ) { // at least one hex input digit exists long currentDigit = getHexDigit(significandString, i); // from nextShift, figure out how many bits need // to be copied, if any switch(nextShift) { // must be negative case -1: // three bits need to be copied in; can // set round bit significand |= ((currentDigit & 0xEL) >> 1); round = (currentDigit & 0x1L) != 0L; break; case -2: // two bits need to be copied in; can // set round and start sticky significand |= ((currentDigit & 0xCL) >> 2); round = (currentDigit &0x2L) != 0L; sticky = (currentDigit & 0x1L) != 0; break; case -3: // one bit needs to be copied in significand |= ((currentDigit & 0x8L)>>3); // Now set round and start sticky, if possible round = (currentDigit &0x4L) != 0L; sticky = (currentDigit & 0x3L) != 0; break; case -4: // all bits copied into significand; set // round and start sticky round = ((currentDigit & 0x8L) != 0); // is top bit set? // nonzeros in three low order bits? sticky = (currentDigit & 0x7L) != 0; break; default: throw new AssertionError("Unexpected shift distance remainder."); // break; } // Round is set; sticky might be set. // For the sticky bit, it suffices to check the // current digit and test for any nonzero digits in // the remaining unprocessed input. i++; while(i < signifLength && !sticky) { currentDigit = getHexDigit(significandString,i); sticky = sticky || (currentDigit != 0); i++; } } // else all of string was seen, round and sticky are // correct as false. // Check for overflow and update exponent accordingly. if (exponent > DoubleConsts.MAX_EXPONENT) { // Infinite result // overflow to properly signed infinity return new FloatingDecimal(sign * Double.POSITIVE_INFINITY); } else { // Finite return value if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result exponent >= DoubleConsts.MIN_EXPONENT) { // The result returned in this block cannot be a // zero or subnormal; however after the // significand is adjusted from rounding, we could // still overflow in infinity. // AND exponent bits into significand; if the // significand is incremented and overflows from // rounding, this combination will update the // exponent correctly, even in the case of // Double.MAX_VALUE overflowing to infinity. significand = (( ((long)exponent + (long)DoubleConsts.EXP_BIAS) << (DoubleConsts.SIGNIFICAND_WIDTH-1)) & DoubleConsts.EXP_BIT_MASK) | (DoubleConsts.SIGNIF_BIT_MASK & significand); } else { // Subnormal or zero // (exponent < DoubleConsts.MIN_EXPONENT) if (exponent < (DoubleConsts.MIN_SUB_EXPONENT -1 )) { // No way to round back to nonzero value // regardless of significand if the exponent is // less than -1075. return new FloatingDecimal(sign * 0.0); } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023 /* * Find bit position to round to; recompute * round and sticky bits, and shift * significand right appropriately. */ sticky = sticky || round; round = false; // Number of bits of significand to preserve is // exponent - abs_min_exp +1 // check: // -1075 +1074 + 1 = 0 // -1023 +1074 + 1 = 52 int bitsDiscarded = 53 - ((int)exponent - DoubleConsts.MIN_SUB_EXPONENT + 1); assert bitsDiscarded >= 1 && bitsDiscarded <= 53; // What to do here: // First, isolate the new round bit round = (significand & (1L << (bitsDiscarded -1))) != 0L; if (bitsDiscarded > 1) { // create mask to update sticky bits; low // order bitsDiscarded bits should be 1 long mask = ~((~0L) << (bitsDiscarded -1)); sticky = sticky || ((significand & mask) != 0L ) ; } // Now, discard the bits significand = significand >> bitsDiscarded; significand = (( ((long)(DoubleConsts.MIN_EXPONENT -1) + // subnorm exp. (long)DoubleConsts.EXP_BIAS) << (DoubleConsts.SIGNIFICAND_WIDTH-1)) & DoubleConsts.EXP_BIT_MASK) | (DoubleConsts.SIGNIF_BIT_MASK & significand); } } // The significand variable now contains the currently // appropriate exponent bits too. /* * Determine if significand should be incremented; * making this determination depends on the least * significant bit and the round and sticky bits. * * Round to nearest even rounding table, adapted from * table 4.7 in "Computer Arithmetic" by IsraelKoren. * The digit to the left of the "decimal" point is the * least significant bit, the digits to the right of * the point are the round and sticky bits * * Number Round(x) * x0.00 x0. * x0.01 x0. * x0.10 x0. * x0.11 x1. = x0. +1 * x1.00 x1. * x1.01 x1. * x1.10 x1. + 1 * x1.11 x1. + 1 */ boolean incremented = false; boolean leastZero = ((significand & 1L) == 0L); if( ( leastZero && round && sticky ) || ((!leastZero) && round )) { incremented = true; significand++; } FloatingDecimal fd = new FloatingDecimal(FpUtils.rawCopySign( Double.longBitsToDouble(significand), sign)); /* * Set roundingDir variable field of fd properly so * that the input string can be properly rounded to a * float value. There are two cases to consider: * * 1. rounding to double discards sticky bit * information that would change the result of a float * rounding (near halfway case between two floats) * * 2. rounding to double rounds up when rounding up * would not occur when rounding to float. * * For former case only needs to be considered when * the bits rounded away when casting to float are all * zero; otherwise, float round bit is properly set * and sticky will already be true. * * The lower exponent bound for the code below is the * minimum (normalized) subnormal exponent - 1 since a * value with that exponent can round up to the * minimum subnormal value and the sticky bit * information must be preserved (i.e. case 1). */ if ((exponent >= FloatConsts.MIN_SUB_EXPONENT-1) && (exponent <= FloatConsts.MAX_EXPONENT ) ){ // Outside above exponent range, the float value // will be zero or infinity. /* * If the low-order 28 bits of a rounded double * significand are 0, the double could be a * half-way case for a rounding to float. If the * double value is a half-way case, the double * significand may have to be modified to round * the the right float value (see the stickyRound * method). If the rounding to double has lost * what would be float sticky bit information, the * double significand must be incremented. If the * double value's significand was itself * incremented, the float value may end up too * large so the increment should be undone. */ if ((significand & 0xfffffffL) == 0x0L) { // For negative values, the sign of the // roundDir is the same as for positive values // since adding 1 increasing the significand's // magnitude and subtracting 1 decreases the // significand's magnitude. If neither round // nor sticky is true, the double value is // exact and no adjustment is required for a // proper float rounding. if( round || sticky) { if (leastZero) { // prerounding lsb is 0 // If round and sticky were both true, // and the least significant // significand bit were 0, the rounded // significand would not have its // low-order bits be zero. Therefore, // we only need to adjust the // significand if round XOR sticky is // true. if (round ^ sticky) { fd.roundDir = 1; } } else { // prerounding lsb is 1 // If the prerounding lsb is 1 and the // resulting significand has its // low-order bits zero, the significand // was incremented. Here, we undo the // increment, which will ensure the // right guard and sticky bits for the // float rounding. if (round) fd.roundDir = -1; } } } } fd.fromHex = true; return fd; } } } /** * Return <code>s</code> with any leading zeros removed. */ static String stripLeadingZeros(String s) { return s.replaceFirst("^0+", ""); } /** * Extract a hexadecimal digit from position <code>position</code> * of string <code>s</code>. */ static int getHexDigit(String s, int position) { int value = Character.digit(s.charAt(position), 16); if (value <= -1 || value >= 16) { throw new AssertionError("Unexpected failure of digit conversion of " + s.charAt(position)); } return value; } } /* * A really, really simple bigint package * tailored to the needs of floating base conversion. */ class FDBigInt { int nWords; // number of words used int data[]; // value: data[0] is least significant public FDBigInt( int v ){ nWords = 1; data = new int[1]; data[0] = v; } public FDBigInt( long v ){ data = new int[2]; data[0] = (int)v; data[1] = (int)(v>>>32); nWords = (data[1]==0) ? 1 : 2; } public FDBigInt( FDBigInt other ){ data = new int[nWords = other.nWords]; System.arraycopy( other.data, 0, data, 0, nWords ); } private FDBigInt( int [] d, int n ){ data = d; nWords = n; } public FDBigInt( long seed, char digit[], int nd0, int nd ){ int n= (nd+8)/9; // estimate size needed. if ( n < 2 ) n = 2; data = new int[n]; // allocate enough space data[0] = (int)seed; // starting value data[1] = (int)(seed>>>32); nWords = (data[1]==0) ? 1 : 2; int i = nd0; int limit = nd-5; // slurp digits 5 at a time. int v; while ( i < limit ){ int ilim = i+5; v = (int)digit[i++]-(int)'0'; while( i <ilim ){ v = 10*v + (int)digit[i++]-(int)'0'; } multaddMe( 100000, v); // ... where 100000 is 10^5. } int factor = 1; v = 0; while ( i < nd ){ v = 10*v + (int)digit[i++]-(int)'0'; factor *= 10; } if ( factor != 1 ){ multaddMe( factor, v ); } } /* * Left shift by c bits. * Shifts this in place. */ public void lshiftMe( int c )throws IllegalArgumentException { if ( c <= 0 ){ if ( c == 0 ) return; // silly. else throw new IllegalArgumentException("negative shift count"); } int wordcount = c>>5; int bitcount = c & 0x1f; int anticount = 32-bitcount; int t[] = data; int s[] = data; if ( nWords+wordcount+1 > t.length ){ // reallocate. t = new int[ nWords+wordcount+1 ]; } int target = nWords+wordcount; int src = nWords-1; if ( bitcount == 0 ){ // special hack, since an anticount of 32 won't go! System.arraycopy( s, 0, t, wordcount, nWords ); target = wordcount-1;