|
1 | 1 | using System; |
| 2 | +using System.Globalization; |
| 3 | +using System.Numerics; |
2 | 4 | using System.Runtime.Serialization; |
3 | 5 |
|
4 | 6 | namespace Python.Runtime |
5 | 7 | { |
6 | 8 | /// <summary> |
7 | | - /// Represents a Python integer object. See the documentation at |
8 | | - /// PY2: https://docs.python.org/2/c-api/int.html |
9 | | - /// PY3: No equivalent |
10 | | - /// for details. |
| 9 | + /// Represents a Python integer object. |
| 10 | + /// See the documentation at https://docs.python.org/3/c-api/long.html |
11 | 11 | /// </summary> |
12 | | - public class PyInt : PyNumber |
| 12 | + public class PyInt : PyNumber, IFormattable |
13 | 13 | { |
14 | 14 | internal PyInt(in StolenReference ptr) : base(ptr) |
15 | 15 | { |
16 | 16 | } |
17 | 17 |
|
18 | | - internal PyInt(BorrowedReference reference): base(reference) |
| 18 | + internal PyInt(BorrowedReference reference) : base(reference) |
19 | 19 | { |
20 | 20 | if (!Runtime.PyInt_Check(reference)) throw new ArgumentException("object is not an int"); |
21 | 21 | } |
@@ -135,6 +135,8 @@ public PyInt(string value) : base(Runtime.PyLong_FromString(value, 0).StealOrThr |
135 | 135 | { |
136 | 136 | } |
137 | 137 |
|
| 138 | + public PyInt(BigInteger value) : this(value.ToString(CultureInfo.InvariantCulture)) { } |
| 139 | + |
138 | 140 | protected PyInt(SerializationInfo info, StreamingContext context) |
139 | 141 | : base(info, context) { } |
140 | 142 |
|
@@ -198,5 +200,35 @@ public long ToInt64() |
198 | 200 | } |
199 | 201 | return val.Value; |
200 | 202 | } |
| 203 | + |
| 204 | + public BigInteger ToBigInteger() |
| 205 | + { |
| 206 | + using var pyHex = Runtime.HexCallable.Invoke(this); |
| 207 | + string hex = pyHex.As<string>(); |
| 208 | + int offset = 0; |
| 209 | + bool neg = false; |
| 210 | + if (hex[0] == '-') |
| 211 | + { |
| 212 | + offset++; |
| 213 | + neg = true; |
| 214 | + } |
| 215 | + byte[] littleEndianBytes = new byte[(hex.Length - offset + 1) / 2]; |
| 216 | + for (; offset < hex.Length; offset++) |
| 217 | + { |
| 218 | + int littleEndianHexIndex = hex.Length - 1 - offset; |
| 219 | + int byteIndex = littleEndianHexIndex / 2; |
| 220 | + int isByteTopHalf = littleEndianHexIndex & 1; |
| 221 | + int valueShift = isByteTopHalf * 4; |
| 222 | + littleEndianBytes[byteIndex] += (byte)(Util.HexToInt(hex[offset]) << valueShift); |
| 223 | + } |
| 224 | + var result = new BigInteger(littleEndianBytes); |
| 225 | + return neg ? -result : result; |
| 226 | + } |
| 227 | + |
| 228 | + public string ToString(string format, IFormatProvider formatProvider) |
| 229 | + { |
| 230 | + using var _ = Py.GIL(); |
| 231 | + return ToBigInteger().ToString(format, formatProvider); |
| 232 | + } |
201 | 233 | } |
202 | 234 | } |
0 commit comments