private Token ReadNumber(char start) { int b = 10; if (start == '0') { if (NextChar('x') || NextChar('X')) { return(ReadHexNumber()); } b = 8; } while (true) { int ch = NextChar(); switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': continue; case '.': return(ReadFloatPostDot()); case 'e': case 'E': return(ReadFloatPostE()); case 'j': case 'J': SetEnd(); return(new ConstantValueToken(LiteralParser.ParseImaginary(GetImage()))); case 'l': case 'L': SetEnd(); return(new ConstantValueToken(LiteralParser.ParseBigInteger(GetImage(), b))); default: Backup(); SetEnd(); return(new ConstantValueToken(ParseInteger(GetImage(), b))); } } }
private Token ReadHexNumber() { while (true) { int ch = NextChar(); string s; switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': continue; case 'l': case 'L': SetEnd(); s = GetImage(); s = s.Substring(2, s.Length - 3); return(new ConstantValueToken(LiteralParser.ParseBigInteger(s, 16))); default: Backup(); SetEnd(); s = GetImage(); s = s.Substring(2, s.Length - 2); return(new ConstantValueToken(ParseInteger(s, 16))); } } }
public static object fromhex(CodeContext /*!*/ context, PythonType /*!*/ cls, string self) { if (String.IsNullOrEmpty(self)) { throw PythonOps.ValueError("expected non empty string"); } self = self.Trim(_whitespace); // look for inf, infinity, nan, etc... double?specialRes = TryParseSpecialFloat(self); if (specialRes != null) { return(specialRes.Value); } // nothing special, parse the hex... if (_fromHexRegex == null) { _fromHexRegex = new Regex("\\A\\s*(?<sign>[-+])?(?:0[xX])?(?<integer>[0-9a-fA-F]+)?(?<fraction>\\.[0-9a-fA-F]*)?(?<exponent>[pP][-+]?[0-9]+)?\\s*\\z"); } Match match = _fromHexRegex.Match(self); if (!match.Success) { throw InvalidHexString(); } var sign = match.Groups["sign"]; var integer = match.Groups["integer"]; var fraction = match.Groups["fraction"]; var exponent = match.Groups["exponent"]; bool isNegative = sign.Success && sign.Value == "-"; BigInteger intVal; if (integer.Success) { intVal = LiteralParser.ParseBigInteger(integer.Value, 16); } else { intVal = BigInteger.Zero; } // combine the integer and fractional parts into one big int BigInteger finalBits; int decimalPointBit = 0; // the number of bits of fractions that we have if (fraction.Success) { BigInteger fractionVal = 0; // add the fractional bits to the integer value for (int i = 1; i < fraction.Value.Length; i++) { char chr = fraction.Value[i]; int val; if (chr >= '0' && chr <= '9') { val = chr - '0'; } else if (chr >= 'a' && chr <= 'f') { val = 10 + chr - 'a'; } else if (chr >= 'A' && chr <= 'Z') { val = 10 + chr - 'A'; } else { // unreachable due to the regex throw new InvalidOperationException(); } fractionVal = (fractionVal << 4) | val; decimalPointBit += 4; } finalBits = (intVal << decimalPointBit) | fractionVal; } else { // we only have the integer value finalBits = intVal; } if (exponent.Success) { int exponentVal = 0; if (!Int32.TryParse(exponent.Value.Substring(1), out exponentVal)) { if (exponent.Value.ToLowerAsciiTriggered().StartsWith("p-") || finalBits == BigInteger.Zero) { double zeroRes = isNegative ? NegativeZero : PositiveZero; if (cls == TypeCache.Double) { return(zeroRes); } return(PythonCalls.Call(cls, zeroRes)); } // integer value is too big, no way we're fitting this in. throw HexStringOverflow(); } // update the bits to truly reflect the exponent if (exponentVal > 0) { finalBits = finalBits << exponentVal; } else if (exponentVal < 0) { decimalPointBit -= exponentVal; } } if ((!exponent.Success && !fraction.Success && !integer.Success) || (!integer.Success && fraction.Length == 1)) { throw PythonOps.ValueError("invalid hexidecimal floating point string '{0}'", self); } if (finalBits == BigInteger.Zero) { if (isNegative) { return(NegativeZero); } else { return(PositiveZero); } } int highBit = finalBits.GetBitCount(); // minus 1 because we'll discard the high bit as it's implicit int finalExponent = highBit - decimalPointBit - 1; while (finalExponent < -1023) { // if we have a number with a very negative exponent // we'll throw away all of the insignificant bits even // if it takes the number down to zero. highBit++; finalExponent++; } if (finalExponent == -1023) { // the exponent bits will be all zero, we're going to be a denormalized number, so // we need to keep the most significant bit. highBit++; } // we have 52 bits to store the exponent. In a normalized number the mantissa has an // implied 1 bit, in denormalized mode it doesn't. int lostBits = highBit - 53; bool rounded = false; if (lostBits > 0) { // we have more bits then we can stick in the double, we need to truncate or round the value. BigInteger finalBitsAndRoundingBit = finalBits >> (lostBits - 1); // check if we need to round up (round half even aka bankers rounding) if ((finalBitsAndRoundingBit & BigInteger.One) != BigInteger.Zero) { // grab the bits we need and the least significant bit which we care about for rounding BigInteger discardedBits = finalBits & ((BigInteger.One << (lostBits - 1)) - 1); if (discardedBits != BigInteger.Zero || // not exactly .5 ((finalBits >> lostBits) & BigInteger.One) != BigInteger.Zero) // or we're exactly .5 and odd and need to round up // round the value up by adding 1 { BigInteger roundedBits = finalBitsAndRoundingBit + 1; // now remove the least significant bit we kept for rounding finalBits = (roundedBits >> 1) & 0xfffffffffffff; // check to see if we overflowed into the next bit (e.g. we had a pattern like ffffff rounding to 1000000) if (roundedBits.GetBitCount() != finalBitsAndRoundingBit.GetBitCount()) { if (finalExponent != -1023) { // we overflowed and we're a normalized number. Discard the new least significant bit so we have // the correct number of bits. We need to raise the exponent to account for this division by 2. finalBits = finalBits >> 1; finalExponent++; } else if (finalBits == BigInteger.Zero) { // we overflowed and we're a denormalized number == 0. Increase the exponent making us a normalized // number. Don't adjust the bits because we're now gaining an implicit 1 bit. finalExponent++; } } rounded = true; } } } if (!rounded) { // no rounding is necessary, just shift the bits to get the mantissa finalBits = (finalBits >> (highBit - 53)) & 0xfffffffffffff; } if (finalExponent > 1023) { throw HexStringOverflow(); } // finally assemble the bits long bits = (long)finalBits; bits |= (((long)finalExponent) + 1023) << 52; if (isNegative) { bits |= unchecked ((long)0x8000000000000000); } double res = BitConverter.Int64BitsToDouble(bits); if (cls == TypeCache.Double) { return(res); } return(PythonCalls.Call(cls, res)); }