コード例 #1
0
ファイル: Tokenizer.cs プロジェクト: weimingtom/IronPythonMod
        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)));
                }
            }
        }
コード例 #2
0
ファイル: Tokenizer.cs プロジェクト: weimingtom/IronPythonMod
        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)));
                }
            }
        }
コード例 #3
0
        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));
        }