Exemplo n.º 1
0
        internal static PythonList Split(this IList <byte> bytes, IList <byte>?sep, int maxsplit, Func <List <byte>, IList <byte> > ctor)
        {
            if (sep == null)
            {
                if (maxsplit == 0)
                {
                    // Corner case for CPython compatibility
                    PythonList result = new PythonList(1);
                    result.AddNoLock(ctor(bytes.LeftStrip() ?? bytes as List <byte> ?? new List <byte>(bytes)));
                    return(result);
                }

                return(SplitInternal(bytes, null, maxsplit, ctor));
            }

            if (sep.Count == 0)
            {
                throw PythonOps.ValueError("empty separator");
            }
            else
            {
                return(SplitInternal(bytes, sep, maxsplit, ctor));
            }
        }
Exemplo n.º 2
0
        public static string /*!*/ __format__(CodeContext /*!*/ context, BigInteger /*!*/ self, [NotNull] string /*!*/ formatSpec)
        {
            StringFormatSpec spec = StringFormatSpec.FromString(formatSpec);

            if (spec.Precision != null)
            {
                throw PythonOps.ValueError("Precision not allowed in integer format specifier");
            }

            BigInteger val = self;

            if (self < 0)
            {
                val = -self;
            }
            string digits;

            switch (spec.Type)
            {
            case 'n':
                CultureInfo culture = context.LanguageContext.NumericCulture;

                if (culture == CultureInfo.InvariantCulture)
                {
                    // invariant culture maps to CPython's C culture, which doesn't
                    // include any formatting info.
                    goto case 'd';
                }

                digits = FormattingHelper.ToCultureString(val, context.LanguageContext.NumericCulture.NumberFormat, spec);
                break;

            case null:
            case 'd':
                if (spec.ThousandsComma)
                {
                    var width = spec.Width ?? 0;
                    // If we're inserting commas, and we're padding with leading zeros.
                    // AlignNumericText won't know where to place the commas,
                    // so force .Net to help us out here.
                    if (spec.Fill.HasValue && spec.Fill.Value == '0' && width > 1)
                    {
                        digits = val.ToString(FormattingHelper.ToCultureString(self, FormattingHelper.InvariantCommaNumberInfo, spec));
                    }
                    else
                    {
                        digits = val.ToString("#,0", CultureInfo.InvariantCulture);
                    }
                }
                else
                {
                    digits = val.ToString("D", CultureInfo.InvariantCulture);
                }
                break;

            case '%':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0.000000%", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("0.000000%", CultureInfo.InvariantCulture);
                }
                break;

            case 'e':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0.000000e+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("0.000000e+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'E':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0.000000E+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("0.000000E+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'f':
            case 'F':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,########0.000000", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("#########0.000000", CultureInfo.InvariantCulture);
                }
                break;

            case 'g':
                if (val >= 1000000)
                {
                    digits = val.ToString("0.#####e+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    goto case 'd';
                }
                else
                {
                    digits = val.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'G':
                if (val >= 1000000)
                {
                    digits = val.ToString("0.#####E+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    goto case 'd';
                }
                else
                {
                    digits = val.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'X':
                digits = AbsToHex(val, false);
                break;

            case 'x':
                digits = AbsToHex(val, true);
                break;

            case 'o':     // octal
                digits = ToOctal(val, true);
                break;

            case 'b':     // binary
                digits = ToBinary(val, false, true);
                break;

            case 'c':     // single char
                int iVal;
                if (spec.Sign != null)
                {
                    throw PythonOps.ValueError("Sign not allowed with integer format specifier 'c'");
                }
                else if (!self.AsInt32(out iVal))
                {
                    throw PythonOps.OverflowError("long int too large to convert to int");
                }
                else if (iVal < 0 || iVal > 0xFF)
                {
                    throw PythonOps.OverflowError("%c arg not in range(0x10000)");
                }

                digits = ScriptingRuntimeHelpers.CharToString((char)iVal);
                break;

            default:
                throw PythonOps.ValueError("Unknown format code '{0}'", spec.Type.ToString());
            }

            Debug.Assert(digits[0] != '-');

            return(spec.AlignNumericText(digits, self.IsZero(), self.IsPositive()));
        }
Exemplo n.º 3
0
        public static string __format__(CodeContext /*!*/ context, int self, [NotNull] string /*!*/ formatSpec)
        {
            StringFormatSpec spec = StringFormatSpec.FromString(formatSpec);

            if (spec.Precision != null)
            {
                throw PythonOps.ValueError("Precision not allowed in integer format specifier");
            }

            string digits;

            switch (spec.Type)
            {
            case 'n':
                CultureInfo culture = PythonContext.GetContext(context).NumericCulture;

                if (culture == CultureInfo.InvariantCulture)
                {
                    // invariant culture maps to CPython's C culture, which doesn't
                    // include any formatting info.
                    goto case 'd';
                }

                digits = self.ToString("N0", PythonContext.GetContext(context).NumericCulture);
                break;

            case null:
            case 'd':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("D", CultureInfo.InvariantCulture);
                }
                break;

            case '%':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0.000000%", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("0.000000%", CultureInfo.InvariantCulture);
                }
                break;

            case 'e':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0.000000e+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("0.000000e+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'E':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0.000000E+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("0.000000E+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'f':
            case 'F':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,########0.000000", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("#########0.000000", CultureInfo.InvariantCulture);
                }
                break;

            case 'g':
                if (self >= 1000000 || self <= -1000000)
                {
                    digits = self.ToString("0.#####e+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'G':
                if (self >= 1000000 || self <= -1000000)
                {
                    digits = self.ToString("0.#####E+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'X':
                digits = ToHex(self, false);
                break;

            case 'x':
                digits = ToHex(self, true);
                break;

            case 'o':     // octal
                digits = ToOctal(self, true);
                break;

            case 'b':     // binary
                digits = ToBinary(self, false);
                break;

            case 'c':     // single char
                if (spec.Sign != null)
                {
                    throw PythonOps.ValueError("Sign not allowed with integer format specifier 'c'");
                }

                if (self < 0 || self > 0xFF)
                {
                    throw PythonOps.OverflowError("%c arg not in range(0x10000)");
                }

                digits = ScriptingRuntimeHelpers.CharToString((char)self);
                break;

            default:
                throw PythonOps.ValueError("Unknown format code '{0}'", spec.Type.ToString());
            }

            if (self < 0 && digits[0] == '-')
            {
                digits = digits.Substring(1);
            }

            return(spec.AlignNumericText(digits, self == 0, self > 0));
        }
Exemplo n.º 4
0
            public void WriteObject(object o)
            {
                List <object> infinite = PythonOps.GetReprInfinite();

                if (infinite.Contains(o))
                {
                    throw PythonOps.ValueError("Marshaled data contains infinite cycle");
                }

                int index = infinite.Count;

                infinite.Add(o);
                try {
                    if (o == null)
                    {
                        _bytes.Add((byte)'N');
                    }
                    else if (o == ScriptingRuntimeHelpers.True || (o is bool && (bool)o))
                    {
                        _bytes.Add((byte)'T');
                    }
                    else if (o == ScriptingRuntimeHelpers.False || (o is bool && (!(bool)o)))
                    {
                        _bytes.Add((byte)'F');
                    }
                    else if (o is IList <byte> )
                    {
                        WriteBytes(o as IList <byte>);
                    }
                    else if (o is string)
                    {
                        WriteString(o as string);
                    }
                    else if (o is int)
                    {
                        WriteInt((int)o);
                    }
                    else if (o is float)
                    {
                        WriteFloat((float)o);
                    }
                    else if (o is double)
                    {
                        WriteFloat((double)o);
                    }
                    else if (o is long)
                    {
                        WriteLong((long)o);
                    }
                    else if (o.GetType() == typeof(PythonList))
                    {
                        WriteList(o);
                    }
                    else if (o.GetType() == typeof(PythonDictionary))
                    {
                        WriteDict(o);
                    }
                    else if (o.GetType() == typeof(PythonTuple))
                    {
                        WriteTuple(o);
                    }
                    else if (o.GetType() == typeof(SetCollection))
                    {
                        WriteSet(o);
                    }
                    else if (o.GetType() == typeof(FrozenSetCollection))
                    {
                        WriteFrozenSet(o);
                    }
                    else if (o is BigInteger)
                    {
                        WriteInteger((BigInteger)o);
                    }
                    else if (o is Complex)
                    {
                        WriteComplex((Complex)o);
                    }
                    else if (o == PythonExceptions.StopIteration)
                    {
                        WriteStopIteration();
                    }
                    else
                    {
                        throw PythonOps.ValueError("unmarshallable object" + o.GetType().ToString());
                    }
                } finally {
                    infinite.RemoveAt(index);
                }
            }
Exemplo n.º 5
0
            public object ReadObject()
            {
                while (_myBytes.MoveNext())
                {
                    byte   cur = _myBytes.Current;
                    object res;
                    switch ((char)cur)
                    {
                    case '(': PushStack(StackType.Tuple); break;

                    case '[': PushStack(StackType.List); break;

                    case '{': PushStack(StackType.Dict); break;

                    case '<': PushStack(StackType.Set); break;

                    case '>': PushStack(StackType.FrozenSet); break;

                    case '0':
                        // end of dictionary
                        if (_stack == null || _stack.Count == 0)
                        {
                            throw PythonOps.ValueError("bad marshal data");
                        }
                        _stack.Peek().StackCount = 0;
                        break;

                    // case 'c': break;
                    default:
                        res = YieldSimple();
                        if (_stack == null)
                        {
                            return(res);
                        }

                        do
                        {
                            res = UpdateStack(res);
                        } while (res != null && _stack.Count > 0);

                        if (_stack.Count == 0)
                        {
                            return(_result);
                        }

                        continue;
                    }

                    // handle empty lists/tuples...
                    if (_stack != null && _stack.Count > 0 && _stack.Peek().StackCount == 0)
                    {
                        ProcStack ps = _stack.Pop();
                        res = ps.StackObj;

                        if (ps.StackType == StackType.Tuple)
                        {
                            res = PythonTuple.Make(res);
                        }
                        else if (ps.StackType == StackType.FrozenSet)
                        {
                            res = FrozenSetCollection.Make(TypeCache.FrozenSet, res);
                        }

                        if (_stack.Count > 0)
                        {
                            // empty list/tuple
                            do
                            {
                                res = UpdateStack(res);
                            } while (res != null && _stack.Count > 0);
                            if (_stack.Count == 0)
                            {
                                break;
                            }
                        }
                        else
                        {
                            _result = res;
                            break;
                        }
                    }
                }

                return(_result);
            }
Exemplo n.º 6
0
        public static double Power(double x, double y)
        {
            if (x == 1.0 || y == 0.0)
            {
                return(1.0);
            }
            else if (double.IsNaN(x) || double.IsNaN(y))
            {
                return(double.NaN);
            }
            else if (x == 0.0)
            {
                if (y > 0.0)
                {
                    // preserve sign if y is a positive, odd int
                    if (y % 2.0 == 1.0)
                    {
                        return(x);
                    }
                    return(0.0);
                }
                else if (y == 0.0)
                {
                    return(1.0);
                }
                else if (double.IsNegativeInfinity(y))
                {
                    return(double.PositiveInfinity);
                }
                throw PythonOps.ZeroDivisionError("0.0 cannot be raised to a negative power");
            }
            else if (double.IsPositiveInfinity(y))
            {
                if (x > 1.0 || x < -1.0)
                {
                    return(double.PositiveInfinity);
                }
                else if (x == -1.0)
                {
                    return(1.0);
                }
                return(0.0);
            }
            else if (double.IsNegativeInfinity(y))
            {
                if (x > 1.0 || x < -1.0)
                {
                    return(0.0);
                }
                else if (x == -1.0)
                {
                    return(1.0);
                }
                return(double.PositiveInfinity);
            }
            else if (double.IsNegativeInfinity(x))
            {
                // preserve negative sign if y is an odd int
                if (Math.Abs(y % 2.0) == 1.0)
                {
                    return(y > 0 ? double.NegativeInfinity : NegativeZero);
                }
                else
                {
                    return(y > 0 ? double.PositiveInfinity : 0.0);
                }
            }
            else if (x < 0 && (Math.Floor(y) != y))
            {
                throw PythonOps.ValueError("negative number cannot be raised to fraction");
            }

            return(PythonOps.CheckMath(x, y, Math.Pow(x, y)));
        }
Exemplo n.º 7
0
 private static Exception InvalidHexString()
 {
     return(PythonOps.ValueError("invalid hexadecimal floating-point string"));
 }
Exemplo n.º 8
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));
        }
Exemplo n.º 9
0
        /// <summary>
        /// Returns the digits for the format spec, no sign is included.
        /// </summary>
        private static string DoubleToFormatString(CodeContext /*!*/ context, double self, StringFormatSpec /*!*/ spec)
        {
            self = Math.Abs(self);
            const int DefaultPrecision = 6;
            int       precision        = spec.Precision ?? DefaultPrecision;

            string digits;

            switch (spec.Type)
            {
            case '%': {
                string fmt = "0." + new string('0', precision) + "%";
                if (spec.ThousandsComma)
                {
                    fmt = "#," + fmt;
                }
                digits = self.ToString(fmt, CultureInfo.InvariantCulture);
                break;
            }

            case 'f':
            case 'F': {
                string fmt = "0." + new string('0', precision);
                if (spec.ThousandsComma)
                {
                    fmt = "#," + fmt;
                }
                digits = self.ToString(fmt, CultureInfo.InvariantCulture);
                break;
            }

            case 'e':
            case 'E': {
                string fmt = "0." + new string('0', precision) + spec.Type + "+00";
                if (spec.ThousandsComma)
                {
                    fmt = "#," + fmt;
                }
                digits = self.ToString(fmt, CultureInfo.InvariantCulture);
                break;
            }

            case '\0':
            case null:
                if (spec.Precision != null)
                {
                    // precision applies to the combined digits before and after the decimal point
                    // so we first need find out how many digits we have before...
                    int    digitCnt = 1;
                    double cur      = self;
                    while (cur >= 10)
                    {
                        cur /= 10;
                        digitCnt++;
                    }

                    // Use exponents if we don't have enough room for all the digits before.  If we
                    // only have as single digit avoid exponents.
                    if (digitCnt > spec.Precision.Value && digitCnt != 1)
                    {
                        // first round off the decimal value
                        self = MathUtils.RoundAwayFromZero(self, 0);

                        // then remove any insignificant digits
                        double pow = Math.Pow(10, digitCnt - Math.Max(spec.Precision.Value, 1));
                        self = self - (self % pow);

                        // finally format w/ the requested precision
                        string fmt = "0.0" + new string('#', spec.Precision.Value);

                        digits = self.ToString(fmt + "e+00", CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        // we're including all the numbers to the right of the decimal we can, we explicitly
                        // round to match CPython's behavior
                        int decimalPoints = Math.Max(spec.Precision.Value - digitCnt, 0);

                        self   = MathUtils.RoundAwayFromZero(self, decimalPoints);
                        digits = self.ToString("0.0" + new string('#', decimalPoints));
                    }
                }
                else
                {
                    // just the default formatting
                    if (IncludeExponent(self))
                    {
                        digits = self.ToString("0.#e+00", CultureInfo.InvariantCulture);
                    }
                    else if (spec.ThousandsComma)
                    {
                        digits = self.ToString("#,0.0###", CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        digits = self.ToString("0.0###", CultureInfo.InvariantCulture);
                    }
                }
                break;

            case 'n':
            case 'g':
            case 'G': {
                // precision applies to the combined digits before and after the decimal point
                // so we first need find out how many digits we have before...
                int    digitCnt = 1;
                double cur      = self;
                while (cur >= 10)
                {
                    cur /= 10;
                    digitCnt++;
                }

                // Use exponents if we don't have enough room for all the digits before.  If we
                // only have as single digit avoid exponents.
                if (digitCnt > precision && digitCnt != 1)
                {
                    // first round off the decimal value
                    self = MathUtils.RoundAwayFromZero(self, 0);

                    // then remove any insignificant digits
                    double pow  = Math.Pow(10, digitCnt - Math.Max(precision, 1));
                    double rest = self / pow;
                    self = self - self % pow;
                    if ((rest % 1) >= .5)
                    {
                        // round up
                        self += pow;
                    }

                    string fmt;
                    if (spec.Type == 'n' && context.LanguageContext.NumericCulture != PythonContext.CCulture)
                    {
                        // we've already figured out, we don't have any digits for decimal points, so just format as a number + exponent
                        fmt = "0";
                    }
                    else if (spec.Precision > 1 || digitCnt > 6)
                    {
                        // include the requested precision to the right of the decimal
                        fmt = "0.#" + new string('#', precision);
                    }
                    else
                    {
                        // zero precision, no decimal
                        fmt = "0";
                    }
                    if (spec.ThousandsComma)
                    {
                        fmt = "#," + fmt;
                    }

                    digits = self.ToString(fmt + (spec.Type == 'G' ? "E+00" : "e+00"), CultureInfo.InvariantCulture);
                }
                else
                {
                    // we're including all the numbers to the right of the decimal we can, we explicitly
                    // round to match CPython's behavior
                    if (self < 1)
                    {
                        // no implicit 0
                        digitCnt--;
                    }
                    int decimalPoints = Math.Max(precision - digitCnt, 0);

                    self = MathUtils.RoundAwayFromZero(self, decimalPoints);

                    if (spec.Type == 'n' && context.LanguageContext.NumericCulture != PythonContext.CCulture)
                    {
                        if (digitCnt != precision && (self % 1) != 0)
                        {
                            digits = self.ToString("#,0.0" + new string('#', decimalPoints));
                        }
                        else
                        {
                            // leave out the decimal if the precision == # of digits or we have a whole number
                            digits = self.ToString("#,0");
                        }
                    }
                    else
                    {
                        if (digitCnt != precision && (self % 1) != 0)
                        {
                            digits = self.ToString("0.0" + new string('#', decimalPoints));
                        }
                        else
                        {
                            // leave out the decimal if the precision == # of digits or we have a whole number
                            digits = self.ToString("0");
                        }
                    }
                }
            }
            break;

            default:
                throw PythonOps.ValueError("Unknown format code '{0}' for object of type 'float'", spec.Type.ToString());
            }

            return(digits);
        }
Exemplo n.º 10
0
        public static string /*!*/ __format__(CodeContext /*!*/ context, BigInteger /*!*/ self, [NotNull] string /*!*/ formatSpec)
        {
            StringFormatSpec spec = StringFormatSpec.FromString(formatSpec);

            if (spec.Precision != null)
            {
                throw PythonOps.ValueError("Precision not allowed in integer format specifier");
            }

            BigInteger val = self;

            if (self < 0)
            {
                val = -self;
            }
            string digits;

            switch (spec.Type)
            {
            case 'n':
                CultureInfo culture = PythonContext.GetContext(context).NumericCulture;

                if (culture == CultureInfo.InvariantCulture)
                {
                    // invariant culture maps to CPython's C culture, which doesn't
                    // include any formatting info.
                    goto case 'd';
                }

                digits = ToCultureString(val, PythonContext.GetContext(context).NumericCulture);
                break;

#if CLR2
            case null:
            case 'd':
                digits = val.ToString();
                break;

            case '%':
                if (val == BigInteger.Zero)
                {
                    digits = "0.000000%";
                }
                else
                {
                    digits = val.ToString() + "00.000000%";
                }
                break;

            case 'e': digits = ToExponent(val, true, 6, 7); break;

            case 'E': digits = ToExponent(val, false, 6, 7); break;

            case 'f':
                if (val != BigInteger.Zero)
                {
                    digits = val.ToString() + ".000000";
                }
                else
                {
                    digits = "0.000000";
                }
                break;

            case 'F':
                if (val != BigInteger.Zero)
                {
                    digits = val.ToString() + ".000000";
                }
                else
                {
                    digits = "0.000000";
                }
                break;

            case 'g':
                if (val >= 1000000)
                {
                    digits = ToExponent(val, true, 0, 6);
                }
                else
                {
                    digits = val.ToString();
                }
                break;

            case 'G':
                if (val >= 1000000)
                {
                    digits = ToExponent(val, false, 0, 6);
                }
                else
                {
                    digits = val.ToString();
                }
                break;
#else
            case null:
            case 'd':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("D", CultureInfo.InvariantCulture);
                }
                break;

            case '%':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0.000000%", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("0.000000%", CultureInfo.InvariantCulture);
                }
                break;

            case 'e':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0.000000e+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("0.000000e+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'E':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0.000000E+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("0.000000E+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'f':
            case 'F':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,########0.000000", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("#########0.000000", CultureInfo.InvariantCulture);
                }
                break;

            case 'g':
                if (val >= 1000000)
                {
                    digits = val.ToString("0.#####e+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'G':
                if (val >= 1000000)
                {
                    digits = val.ToString("0.#####E+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString(CultureInfo.InvariantCulture);
                }
                break;
#endif
            case 'X':
                digits = AbsToHex(val, false);
                break;

            case 'x':
                digits = AbsToHex(val, true);
                break;

            case 'o':     // octal
                digits = ToOctal(val, true);
                break;

            case 'b':     // binary
                digits = ToBinary(val, false, true);
                break;

            case 'c':     // single char
                int iVal;
                if (spec.Sign != null)
                {
                    throw PythonOps.ValueError("Sign not allowed with integer format specifier 'c'");
                }
                else if (!self.AsInt32(out iVal))
                {
                    throw PythonOps.OverflowError("long int too large to convert to int");
                }
                else if (iVal < 0 || iVal > 0xFF)
                {
                    throw PythonOps.OverflowError("%c arg not in range(0x10000)");
                }

                digits = ScriptingRuntimeHelpers.CharToString((char)iVal);
                break;

            default:
                throw PythonOps.ValueError("Unknown format code '{0}'", spec.Type.ToString());
            }

            Debug.Assert(digits[0] != '-');

            return(spec.AlignNumericText(digits, self.IsZero(), self.IsPositive()));
        }
Exemplo n.º 11
0
        public static string __format__(CodeContext /*!*/ context, int self, [NotNull] string /*!*/ formatSpec)
        {
            StringFormatSpec spec = StringFormatSpec.FromString(formatSpec);

            if (spec.Precision != null)
            {
                throw PythonOps.ValueError("Precision not allowed in integer format specifier");
            }

            string digits;
            int    width = 0;

            switch (spec.Type)
            {
            case 'n':
                CultureInfo culture = context.LanguageContext.NumericCulture;

                if (culture == CultureInfo.InvariantCulture)
                {
                    // invariant culture maps to CPython's C culture, which doesn't
                    // include any formatting info.
                    goto case 'd';
                }
                width = spec.Width ?? 0;

                // If we're padding with leading zeros and we might be inserting
                // culture sensitive number group separators. (i.e. commas)
                // So use FormattingHelper.ToCultureString for that support.
                if (spec.Fill.HasValue && spec.Fill.Value == '0' && width > 1)
                {
                    digits = FormattingHelper.ToCultureString(self, culture.NumberFormat, spec);
                }
                else
                {
                    digits = self.ToString("N0", culture);
                }
                break;

            case null:
            case 'd':
                if (spec.ThousandsComma)
                {
                    width = spec.Width ?? 0;

                    // If we're inserting commas, and we're padding with leading zeros.
                    // AlignNumericText won't know where to place the commas,
                    // so use FormattingHelper.ToCultureString for that support.
                    if (spec.Fill.HasValue && spec.Fill.Value == '0' && width > 1)
                    {
                        digits = FormattingHelper.ToCultureString(self, FormattingHelper.InvariantCommaNumberInfo, spec);
                    }
                    else
                    {
                        digits = self.ToString("#,0", CultureInfo.InvariantCulture);
                    }
                }
                else
                {
                    digits = self.ToString("D", CultureInfo.InvariantCulture);
                }
                break;

            case '%':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0.000000%", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("0.000000%", CultureInfo.InvariantCulture);
                }
                break;

            case 'e':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0.000000e+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("0.000000e+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'E':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0.000000E+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("0.000000E+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'f':
            case 'F':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,########0.000000", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("#########0.000000", CultureInfo.InvariantCulture);
                }
                break;

            case 'g':
                if (self >= 1000000 || self <= -1000000)
                {
                    digits = self.ToString("0.#####e+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    // Handle the common case in 'd'.
                    goto case 'd';
                }
                else
                {
                    digits = self.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'G':
                if (self >= 1000000 || self <= -1000000)
                {
                    digits = self.ToString("0.#####E+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    // Handle the common case in 'd'.
                    goto case 'd';
                }
                else
                {
                    digits = self.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'X':
                digits = ToHex(self, false);
                break;

            case 'x':
                digits = ToHex(self, true);
                break;

            case 'o':     // octal
                digits = ToOctal(self, true);
                break;

            case 'b':     // binary
                digits = ToBinary(self, false);
                break;

            case 'c':     // single char
                if (spec.Sign != null)
                {
                    throw PythonOps.ValueError("Sign not allowed with integer format specifier 'c'");
                }

                if (self < 0 || self > 0xFF)
                {
                    throw PythonOps.OverflowError("%c arg not in range(0x10000)");
                }

                digits = ScriptingRuntimeHelpers.CharToString((char)self);
                break;

            default:
                throw PythonOps.ValueError("Unknown format code '{0}'", spec.Type.ToString());
            }

            if (self < 0 && digits[0] == '-')
            {
                digits = digits.Substring(1);
            }

            return(spec.AlignNumericText(digits, self == 0, self > 0));
        }
Exemplo n.º 12
0
        internal static List <byte> /*!*/ FromHex(string /*!*/ @string)
        {
            if (@string == null)
            {
                throw PythonOps.TypeError("expected str, got NoneType");
            }

            List <byte> res = new List <byte>();

            for (int i = 0; i < @string.Length; i++)
            {
                char c = @string[i];

                int iVal = 0;

                if (Char.IsDigit(c))
                {
                    iVal = (c - '0') * 16;
                }
                else if (c >= 'A' && c <= 'F')
                {
                    iVal = (c - 'A' + 10) * 16;
                }
                else if (c >= 'a' && c <= 'f')
                {
                    iVal = (c - 'a' + 10) * 16;
                }
                else if (c == ' ')
                {
                    continue;
                }
                else
                {
                    throw PythonOps.ValueError("non-hexadecimal number found in fromhex() arg at position {0}", i);
                }

                i++;
                if (i == @string.Length)
                {
                    throw PythonOps.ValueError("non-hexadecimal number found in fromhex() arg at position {0}", i - 1);
                }

                c = @string[i];
                if (Char.IsDigit(c))
                {
                    iVal += c - '0';
                }
                else if (c >= 'A' && c <= 'F')
                {
                    iVal += c - 'A' + 10;
                }
                else if (c >= 'a' && c <= 'f')
                {
                    iVal += c - 'a' + 10;
                }
                else
                {
                    throw PythonOps.ValueError("non-hexadecimal number found in fromhex() arg at position {0}", i);
                }
                res.Add((byte)iVal);
            }
            return(res);
        }
Exemplo n.º 13
0
        public static Bytes to_bytes(Int64 value, int length, [NotNone] string byteorder, bool signed = false)
        {
            // TODO: signed should be a keyword only argument
            bool isLittle = (byteorder == "little");

            if (!isLittle && byteorder != "big")
            {
                throw PythonOps.ValueError("byteorder must be either 'little' or 'big'");
            }

            if (length < 0)
            {
                throw PythonOps.ValueError("length argument must be non-negative");
            }
            if (!signed && value < 0)
            {
                throw PythonOps.OverflowError("can't convert negative int to unsigned");
            }

            if (value == 0)
            {
                return(Bytes.Make(new byte[length]));
            }

            var bytes = new byte[length];
            int cur, end, step;

            if (isLittle)
            {
                cur = 0; end = length; step = 1;
            }
            else
            {
                cur = length - 1; end = -1; step = -1;
            }

            if (!signed || value >= 0)
            {
                ulong uvalue = unchecked ((ulong)value);
                do
                {
                    if (cur == end)
                    {
                        ThrowOverflow();
                    }
                    bytes[cur] = (byte)(uvalue & 0xFF);
                    uvalue   >>= 8;
                    cur       += step;
                } while (uvalue != 0);
            }
            else
            {
                byte curbyte;
                do
                {
                    if (cur == end)
                    {
                        ThrowOverflow();
                    }
                    bytes[cur] = curbyte = (byte)(value & 0xFF);
                    value    >>= 8;
                    cur       += step;
                } while (value != -1 || (curbyte & 0x80) == 0);

                while (cur != end)
                {
                    bytes[cur] = 0xFF;
                    cur       += step;
                }
            }

            return(Bytes.Make(bytes));
Exemplo n.º 14
0
 public static BigInteger op_RightShift(BigInteger x, int y) {
     if (y < 0) {
         throw PythonOps.ValueError("negative shift count");
     }
     return x >> y;
 }