Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Support forBigInteger (C#) <->PyInt#1710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
filmor merged 1 commit intopythonnet:masterfromlosttech:features/PyIntBig
Apr 8, 2022
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletionsCHANGELOG.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,6 +22,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
- .NET collection types now implement standard Python collection interfaces from `collections.abc`.
See [Mixins/collections.py](src/runtime/Mixins/collections.py).
- .NET arrays implement Python buffer protocol
- Python integer interoperability with `System.Numerics.BigInteger`
- Python.NET will correctly resolve .NET methods, that accept `PyList`, `PyInt`,
and other `PyObject` derived types when called from Python.
- .NET classes, that have `__call__` method are callable from Python
Expand Down
20 changes: 20 additions & 0 deletionssrc/embed_tests/TestConverter.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

using NUnit.Framework;

Expand DownExpand Up@@ -131,6 +132,25 @@ public void ToNullable()
Assert.AreEqual(Const, ni);
}

[Test]
public void BigIntExplicit()
{
BigInteger val = 42;
var i = new PyInt(val);
var ni = i.As<BigInteger>();
Assert.AreEqual(val, ni);
var nullable = i.As<BigInteger?>();
Assert.AreEqual(val, nullable);
}

[Test]
public void PyIntImplicit()
{
var i = new PyInt(1);
var ni = (PyObject)i.As<object>();
Assert.AreEqual(i.rawPtr, ni.rawPtr);
}

[Test]
public void ToPyList()
{
Expand Down
34 changes: 34 additions & 0 deletionssrc/embed_tests/TestPyInt.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
using System;
using System.Globalization;
using System.Linq;
using System.Numerics;

using NUnit.Framework;
using Python.Runtime;

Expand DownExpand Up@@ -179,5 +183,35 @@ public void TestConvertToInt64()
Assert.IsInstanceOf(typeof(long), a.ToInt64());
Assert.AreEqual(val, a.ToInt64());
}

[Test]
public void ToBigInteger()
{
int[] simpleValues =
{
0, 1, 2,
0x10,
0x123,
0x1234,
};
simpleValues = simpleValues.Concat(simpleValues.Select(v => -v)).ToArray();

foreach (var val in simpleValues)
{
var pyInt = new PyInt(val);
Assert.AreEqual((BigInteger)val, pyInt.ToBigInteger());
}
}

[Test]
public void ToBigIntegerLarge()
{
BigInteger val = BigInteger.Pow(2, 1024) + 3;
var pyInt = new PyInt(val);
Assert.AreEqual(val, pyInt.ToBigInteger());
val = -val;
pyInt = new PyInt(val);
Assert.AreEqual(val, pyInt.ToBigInteger());
}
}
}
8 changes: 8 additions & 0 deletionssrc/runtime/Converter.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -455,6 +455,14 @@ internal static bool ToManagedValue(BorrowedReference value, Type obType,
}
}

if (obType == typeof(System.Numerics.BigInteger)
&& Runtime.PyInt_Check(value))
{
using var pyInt = new PyInt(value);
result = pyInt.ToBigInteger();
return true;
}

return ToPrimitive(value, obType, out result, setError);
}

Expand Down
44 changes: 38 additions & 6 deletionssrc/runtime/PythonTypes/PyInt.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
using System;
using System.Globalization;
using System.Numerics;
using System.Runtime.Serialization;

namespace Python.Runtime
{
/// <summary>
/// Represents a Python integer object. See the documentation at
/// PY2: https://docs.python.org/2/c-api/int.html
/// PY3: No equivalent
/// for details.
/// Represents a Python integer object.
/// See the documentation at https://docs.python.org/3/c-api/long.html
/// </summary>
public class PyInt : PyNumber
public class PyInt : PyNumber, IFormattable
{
internal PyInt(in StolenReference ptr) : base(ptr)
{
}

internal PyInt(BorrowedReference reference): base(reference)
internal PyInt(BorrowedReference reference): base(reference)
{
if (!Runtime.PyInt_Check(reference)) throw new ArgumentException("object is not an int");
}
Expand DownExpand Up@@ -135,6 +135,8 @@ public PyInt(string value) : base(Runtime.PyLong_FromString(value, 0).StealOrThr
{
}

public PyInt(BigInteger value) : this(value.ToString(CultureInfo.InvariantCulture)) { }

protected PyInt(SerializationInfo info, StreamingContext context)
: base(info, context) { }

Expand DownExpand Up@@ -198,5 +200,35 @@ public long ToInt64()
}
return val.Value;
}

public BigInteger ToBigInteger()
{
using var pyHex = Runtime.HexCallable.Invoke(this);
string hex = pyHex.As<string>();
int offset = 0;
bool neg = false;
if (hex[0] == '-')
{
offset++;
neg = true;
}
byte[] littleEndianBytes = new byte[(hex.Length - offset + 1) / 2];
for (; offset < hex.Length; offset++)
{
int littleEndianHexIndex = hex.Length - 1 - offset;
int byteIndex = littleEndianHexIndex / 2;
int isByteTopHalf = littleEndianHexIndex & 1;
int valueShift = isByteTopHalf * 4;
littleEndianBytes[byteIndex] += (byte)(Util.HexToInt(hex[offset]) << valueShift);
}
var result = new BigInteger(littleEndianBytes);
return neg ? -result : result;
}

public string ToString(string format, IFormatProvider formatProvider)
{
using var _ = Py.GIL();
return ToBigInteger().ToString(format, formatProvider);
}
}
}
16 changes: 11 additions & 5 deletionssrc/runtime/Runtime.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -179,6 +179,7 @@ internal static void Initialize(bool initSigs = false)

clrInterop = GetModuleLazy("clr.interop");
inspect = GetModuleLazy("inspect");
hexCallable = new(() => new PyString("%x").GetAttr("__mod__"));
}

static void NewRun()
Expand DownExpand Up@@ -279,8 +280,9 @@ internal static void Shutdown()

Exceptions.Shutdown();
PythonEngine.InteropConfiguration.Dispose();
DisposeLazyModule(clrInterop);
DisposeLazyModule(inspect);
DisposeLazyObject(clrInterop);
DisposeLazyObject(inspect);
DisposeLazyObject(hexCallable);
PyObjectConversions.Reset();

PyGC_Collect();
Expand DownExpand Up@@ -352,11 +354,11 @@ static bool TryCollectingGarbage(int runs, bool forceBreakLoops)
public static bool TryCollectingGarbage(int runs)
=> TryCollectingGarbage(runs, forceBreakLoops: false);

static voidDisposeLazyModule(Lazy<PyObject>module)
static voidDisposeLazyObject(Lazy<PyObject>pyObject)
{
if (module.IsValueCreated)
if (pyObject.IsValueCreated)
{
module.Value.Dispose();
pyObject.Value.Dispose();
}
}

Expand DownExpand Up@@ -489,8 +491,12 @@ private static void NullGCHandles(IEnumerable<IntPtr> objects)

private static Lazy<PyObject> inspect;
internal static PyObject InspectModule => inspect.Value;

private static Lazy<PyObject> clrInterop;
internal static PyObject InteropModule => clrInterop.Value;

private static Lazy<PyObject> hexCallable;
internal static PyObject HexCallable => hexCallable.Value;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.

internal static BorrowedReference CLRMetaType => PyCLRMetaType;
Expand Down
7 changes: 7 additions & 0 deletionssrc/runtime/Util/Util.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -141,6 +141,13 @@ internal static string ReadStringResource(this System.Reflection.Assembly assemb
return reader.ReadToEnd();
}

public static int HexToInt(char hex) => hex switch
{
>= '0' and <= '9' => hex - '0',
>= 'a' and <= 'f' => hex - 'a' + 10,
_ => throw new ArgumentOutOfRangeException(nameof(hex)),
};

public static IEnumerator<T> GetEnumerator<T>(this IEnumerator<T> enumerator) => enumerator;

public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> source)
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp