Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
.
  • Loading branch information
Mick Phillips committed Feb 3, 2024
1 parent 31116c9 commit 8055572
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 72 deletions.
32 changes: 24 additions & 8 deletions Src/IronPython/Runtime/Operations/IntOps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public static object __new__(CodeContext context, PythonType cls) {
}

#region Binary Operators

[SpecialName]
public static object FloorDivide(int x, int y) {
if (y == -1 && x == Int32.MinValue) {
Expand Down Expand Up @@ -414,15 +414,14 @@ public static object __coerce__(CodeContext context, int x, object o) {
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':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
CultureInfo culture = context.LanguageContext.NumericCulture;

if (culture == CultureInfo.InvariantCulture) {
Expand All @@ -444,6 +443,9 @@ public static string __format__(CodeContext/*!*/ context, int self, [NotNull]str
break;
case null:
case 'd':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
if (spec.ThousandsComma) {
width = spec.Width ?? 0;

Expand Down Expand Up @@ -511,22 +513,36 @@ public static string __format__(CodeContext/*!*/ context, int self, [NotNull]str
}
break;
case 'X':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = ToHex(self, false);
break;
case 'x':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = ToHex(self, true);
break;
case 'o': // octal
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = ToOctal(self, true);
break;
case 'b': // binary
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = ToBinary(self, false);
break;
case 'c': // single char
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
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)");
}
Expand Down Expand Up @@ -588,7 +604,7 @@ internal static string ToBinary(int self) {
if (self == Int32.MinValue) {
return "-0b10000000000000000000000000000000";
}

string res = ToBinary(self, true);
if (self < 0) {
res = "-" + res;
Expand Down Expand Up @@ -619,7 +635,7 @@ private static string ToBinary(int self, bool includeType) {
} else {
digits = "10000000000000000000000000000000";
}

if (includeType) {
digits = "0b" + digits;
}
Expand Down
63 changes: 42 additions & 21 deletions Src/IronPython/Runtime/Operations/LongOps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static object __new__(CodeContext context, PythonType cls, string s, int
public static object __new__(CodeContext/*!*/ context, PythonType cls, IList<byte> s) {
return __new__(context, cls, s, 10);
}

[StaticExtensionMethod]
public static object __new__(CodeContext/*!*/ context, PythonType cls, IList<byte> s, int redix) {
object value;
Expand Down Expand Up @@ -86,7 +86,7 @@ public static object __new__(CodeContext context, PythonType cls, object x) {
if (x is double) return ReturnObject(context, cls, DoubleOps.__long__((double)x));
if (x is int) return ReturnObject(context, cls, (BigInteger)(int)x);
if (x is BigInteger) return ReturnObject(context, cls, x);

if (x is Complex) throw PythonOps.TypeError("can't convert complex to long; use long(abs(z))");

if (x is decimal) {
Expand Down Expand Up @@ -331,7 +331,7 @@ public static double TrueDivide([NotNull]BigInteger x, [NotNull]BigInteger y) {
// otherwise give the user the truncated result if the result fits in a float
BigInteger rem;
BigInteger res = BigInteger.DivRem(x, y, out rem);
if (res.TryToFloat64(out fRes)) {
if (res.TryToFloat64(out fRes)) {
if(rem != BigInteger.Zero) {
// try and figure out the fractional portion
BigInteger fraction = y / rem;
Expand All @@ -343,7 +343,7 @@ public static double TrueDivide([NotNull]BigInteger x, [NotNull]BigInteger y) {
}

return fRes;
}
}

// otherwise report an error
throw PythonOps.OverflowError("long/long too large for a float");
Expand Down Expand Up @@ -444,7 +444,7 @@ public static string __oct__(BigInteger x) {
}

public static string __hex__(BigInteger x) {
// CPython 2.5 prints letters in lowercase, with a capital L.
// CPython 2.5 prints letters in lowercase, with a capital L.
if (x < 0) {
return "-0x" + (-x).ToString(16).ToLower() + "L";
} else {
Expand Down Expand Up @@ -540,7 +540,7 @@ public static int Compare(BigInteger x, BigInteger y) {
[SpecialName]
public static int Compare(BigInteger x, int y) {
int ix;
if (x.AsInt32(out ix)) {
if (x.AsInt32(out ix)) {
return ix == y ? 0 : ix > y ? 1 : -1;
}

Expand Down Expand Up @@ -568,7 +568,7 @@ public static int Compare(BigInteger x, [NotNull]Extensible<double> y) {
}

[SpecialName]
public static int Compare(BigInteger x, decimal y) {
public static int Compare(BigInteger x, decimal y) {
return DecimalOps.__cmp__(x, y);
}

Expand Down Expand Up @@ -604,7 +604,7 @@ public static int __hash__(BigInteger self) {
}

// Call the DLR's BigInteger hash function, which will return an int32 representation of
// b if b is within the int32 range. We use that as an optimization for hashing, and
// b if b is within the int32 range. We use that as an optimization for hashing, and
// assert the assumption below.
int hash = self.GetHashCode();
#if DEBUG
Expand Down Expand Up @@ -637,7 +637,7 @@ public static float ToFloat(BigInteger/*!*/ self) {
}

#region Binary Ops

[PythonHidden]
public static BigInteger Xor(BigInteger x, BigInteger y) {
return x ^ y;
Expand Down Expand Up @@ -706,7 +706,7 @@ public static bool AsUInt32(BigInteger self, out uint res) {
public static bool AsUInt64(BigInteger self, out ulong res) {
return self.AsUInt64(out res);
}

#endregion

#region Direct Conversions
Expand Down Expand Up @@ -907,18 +907,17 @@ public static int GetWordCount(BigInteger self) {
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':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
CultureInfo culture = context.LanguageContext.NumericCulture;

if (culture == CultureInfo.InvariantCulture) {
Expand All @@ -931,6 +930,9 @@ public static int GetWordCount(BigInteger self) {
break;
case null:
case 'd':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
if (spec.ThousandsComma) {
var width = spec.Width ?? 0;
// If we're inserting commas, and we're padding with leading zeros.
Expand Down Expand Up @@ -995,22 +997,41 @@ public static int GetWordCount(BigInteger self) {
}
break;
case 'X':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = AbsToHex(val, false);
break;
case 'x':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = AbsToHex(val, true);
break;
case 'o': // octal
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = ToOctal(val, true);
break;
case 'b': // binary
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = ToBinary(val, false, true);
break;
case 'c': // single char
int iVal;
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
if (spec.Sign != null) {
throw PythonOps.ValueError("Sign not allowed with integer format specifier 'c'");
} else if (!self.AsInt32(out iVal)) {
}
int iVal;
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)");
Expand All @@ -1035,7 +1056,7 @@ private static string ToOctal(BigInteger val, bool lowercase) {
return ToDigits(val, 8, lowercase);
}

internal static string ToBinary(BigInteger val) {
internal static string ToBinary(BigInteger val) {
string res = ToBinary(val.Abs(), true, true);
if (val.IsNegative()) {
res = "-" + res;
Expand All @@ -1047,7 +1068,7 @@ private static string ToBinary(BigInteger val, bool includeType, bool lowercase)
Debug.Assert(!val.IsNegative());

string digits = ToDigits(val, 2, lowercase);

if (includeType) {
digits = (lowercase ? "0b" : "0B") + digits;
}
Expand All @@ -1062,7 +1083,7 @@ private static string ToBinary(BigInteger val, bool includeType, bool lowercase)

StringBuilder tmp = new StringBuilder();
tmp.Append(digits[0]);

for (int i = 1; i < maxPrecision && i < digits.Length; i++) {
// append if we have a significant digit or if we are forcing a minimum precision
if (digits[i] != '0' || i <= minPrecision) {
Expand Down Expand Up @@ -1129,7 +1150,7 @@ private static string ToBinary(BigInteger val, bool includeType, bool lowercase)
for (int i = str.Length - 1; i >= 0; i--) {
res.Append(str[i]);
}

return res.ToString();
}
}
Expand Down
Loading

0 comments on commit 8055572

Please sign in to comment.