dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.25k stars 4.73k forks source link

[API Proposal]: Add support for Int256 and UInt256 data types #80663

Open benaadams opened 1 year ago

benaadams commented 1 year ago

Background and motivation

256 bit integers are becoming more commonly used with 3,189 questions on StackOverflow and use in .NET for example in the application NethermindEth and library Nethereum.

While BigInteger can be used a dedicated type can provide x14 gains and much lower memory usage than BigInteger through not needing to use an arrays to represent data. The implementation can also achieve x2.5 gains using Avx2 vs a software implementation although the approach starts to become exotic https://github.com/NethermindEth/int256/pull/24

API Proposal

namespace System
{
    public readonly struct Int256
        : IComparable,
          IComparable<Int256>,
          IEquatable<Int256>,
          IBinaryInteger<Int256>,
          IMinMaxValue<Int256>,
          ISpanFormattable,
          ISignedNumber<Int256>
    {
        // Constructors

        public Int256(ReadOnlySpan<byte> bytes, bool isBigEndian = false);
        public Int256(uint r0, uint r1, uint r2, uint r3, uint r4, uint r5, uint r6, uint r7);
        public Int256(ulong u0 = 0, ulong u1 = 0, ulong u2 = 0, ulong u3 = 0);
        public Int256(UInt128 upper, UInt128 lower);

        // Properties

        public static Int256 AdditiveIdentity { get; }

        public static Int256 MaxValue { get; }
        public static Int256 MinValue { get; }

        public static Int256 MultiplicativeIdentity { get; }

        public static Int256 NegativeOne { get; }
        public static Int256 One { get; }
        public static Int256 Zero { get; }

        // Addition Operators

        public static Int256 operator +(Int256 left, Int256 right);
        public static Int256 operator checked +(Int256 left, Int256 right);

        // Bitwise Operators

        public static Int256 operator &(Int256 left, Int256 right);
        public static Int256 operator |(Int256 left, Int256 right);
        public static Int256 operator ^(Int256 left, Int256 right);
        public static Int256 operator ~(Int256 left, Int256 right);

        // Comparison Operators

        public static bool operator <(Int256 left, Int256 right);
        public static bool operator <=(Int256 left, Int256 right);
        public static bool operator >(Int256 left, Int256 right);
        public static bool operator >=(Int256 left, Int256 right);

        // Conversion From Operators

        public static implicit operator Int256(byte value);
        public static implicit operator Int256(char value);
        public static implicit operator Int256(short value);
        public static implicit operator Int256(int value);
        public static implicit operator Int256(long value);
        public static implicit operator Int256(Int128 value);
        public static implicit operator Int256(nint value);
        public static implicit operator Int256(sbyte value);
        public static implicit operator Int256(ushort value);
        public static implicit operator Int256(uint value);
        public static implicit operator Int256(ulong value);
        public static implicit operator Int256(nuint value);
        public static implicit operator Int256(UInt128 value);

        public static explicit operator Int256(double value);
        public static explicit operator Int256(decimal value);
        public static explicit operator Int256(Half value);
        public static explicit operator Int256(float value);

        public static explicit operator Int256(UInt256 value);

        // Conversion To Operators

        public static explicit operator byte(Int256 value);
        public static explicit operator char(Int256 value);
        public static explicit operator short(Int256 value);
        public static explicit operator int(Int256 value);
        public static explicit operator long(Int256 value);
        public static explicit operator Int128(Int256 value);
        public static explicit operator nint(Int256 value);
        public static explicit operator sbyte(Int256 value);
        public static explicit operator ushort(Int256 value);
        public static explicit operator uint(Int256 value);
        public static explicit operator ulong(Int256 value);
        public static explicit operator nuint(Int256 value);
        public static explicit operator UInt128(Int256 value);

        public static explicit operator double(Int256 value);
        public static explicit operator decimal(Int256 value);
        public static explicit operator Half(Int256 value);
        public static explicit operator float(Int256 value);

        // Decrement Operators

        public static Int256 operator --(Int256 value);
        public static Int256 operator checked --(Int256 value);

        // Division Operators

        public static Int256 operator /(Int256 left, Int256 right);
        public static Int256 operator checked /(Int256 left, Int256 right);

        // Equality Operators

        public static bool operator ==(Int256 left, Int256 right);
        public static bool operator !=(Int256 left, Int256 right);

        // Increment Operators

        public static Int256 operator ++(Int256 value);
        public static Int256 operator checked ++(Int256 value);

        // Modulus Operators

        public static Int256 operator %(Int256 left, Int256 right);

        // Multiply Operators

        public static Int256 operator *(Int256 left, Int256 right);
        public static Int256 operator checked *(Int256 left, Int256 right);

        // Shift Operators

        public static Int256 operator <<(Int256 value, int shiftAmount);
        public static Int256 operator >>(Int256 value, int shiftAmount);
        public static Int256 operator >>>(Int256 value, int shiftAmount);

        // Subtraction Operators

        public static Int256 operator -(Int256 left, Int256 right);
        public static Int256 operator checked -(Int256 left, Int256 right);

        // Unary Negation/Plus Operators

        public static Int256 operator +(Int256 value);
        public static Int256 operator -(Int256 value);
        public static Int256 operator checked -(Int256 value);

        // Comparison Methods

        public int CompareTo(object? obj);
        public int CompareTo(Int256 other);

        // Equality Methods

        public override bool Equals([NotNullWhen(true)] object? obj);
        public bool Equals(Int256 other);

        // Hashing Methods

        public override int GetHashCode();

        // Parsing Methods

        public static Int256 Parse(string s);
        public static Int256 Parse(string s, NumberStyles style);
        public static Int256 Parse(string s, IFormatProvider? provider);
        public static Int256 Parse(string s, NumberStyles style, IFormatProvider? provider);
        public static Int256 Parse(ReadOnlySpan<char> s, IFormatProvider? provider);
        public static Int256 Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null);

        public static bool TryParse([NotNullWhen(true)] string? s, out Int256 result);
        public static bool TryParse(ReadOnlySpan<char> s, out Int256 result);
        public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out long result);
        public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out Int256 result);
        public static bool TryParse(ReadOnlySpan<char> s, IFormatProvider? provider, out Int256 result);
        public static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider? provider, out Int256 result);

        // Formatting Methods

        public override string ToString();
        public string ToString(IFormatProvider? provider);
        public string ToString(string? format);
        public string ToString(string? format, IFormatProvider? provider);

        public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default, IFormatProvider? provider = null);

        // Binary Integer Methods

        public static Int256 LeadingZeroCount(Int256 value);
        public static Int256 PopCount(Int256 value);
        public static Int256 RotateLeft(Int256 value);
        public static Int256 RotateRight(Int256 value);
        public static Int256 TrailingZeroCount(Int256 value);

        // Binary Number Methods

        public static bool IsPow2(Int256 value);
        public static Int256 Log2(Int256 value);

        // Number Methods

        public static Int256 Abs(Int256 value);
        public static Int256 Clamp(Int256 value, Int256 min, Int256 max);
        public static Int256 CreateChecked<TOther>(TOther value) where TOther : INumber<TOther>;
        public static Int256 CreateSaturating<TOther>(TOther value) where TOther : INumber<TOther>;
        public static Int256 CreateTruncating<TOther>(TOther value) where TOther : INumber<TOther>;
        public static (Int256 Quotient, Int256 Remainder) DivRem(Int256 left, Int256 right);
        public static Int256 Max(Int256 x, Int256 y);
        public static Int256 Min(Int256 x, Int256 y);
        public static Int256 Sign(Int256 value);
        public static bool TryCreate<TOther>(TOther value, out Int256 result) where TOther : INumber<TOther>;
    }

    public readonly struct UInt256
        : IComparable,
          IComparable<UInt256>,
          IEquatable<UInt256>,
          IBinaryInteger<UInt256>,
          IMinMaxValue<UInt256>,
          ISpanFormattable,
          IUnsignedNumber<UInt256>
    {
        // Same members as Int256, but taking/returning UInt256
        // NegativeOne is not defined/exposed
        // Conversion From/To operators differ as per below

        // Conversion From Operators

        public static implicit operator UInt256(byte value);
        public static implicit operator UInt256(char value);
        public static implicit operator UInt256(ushort value);
        public static implicit operator UInt256(uint value);
        public static implicit operator UInt256(ulong value);
        public static implicit operator UInt256(UInt128 value);
        public static implicit operator UInt256(nuint value);

        public static explicit operator UInt256(short value);
        public static explicit operator UInt256(int value);
        public static explicit operator UInt256(long value);
        public static explicit operator UInt256(Int128 value);
        public static explicit operator UInt256(nint value);
        public static explicit operator UInt256(sbyte value);

        public static explicit operator UInt256(double value);
        public static explicit operator UInt256(decimal value);
        public static explicit operator UInt256(Half value);
        public static explicit operator UInt256(float value);

        public static explicit operator UInt256(Int256 value);

        // Conversion To Operators

        public static explicit operator byte(UInt256 value);
        public static explicit operator char(UInt256 value);
        public static explicit operator short(UInt256 value);
        public static explicit operator int(UInt256 value);
        public static explicit operator long(UInt256 value);
        public static explicit operator Int128(UInt256 value);
        public static explicit operator nint(UInt256 value);
        public static explicit operator sbyte(UInt256 value);
        public static explicit operator ushort(UInt256 value);
        public static explicit operator uint(UInt256 value);
        public static explicit operator ulong(UInt256 value);
        public static explicit operator UInt128(UInt256 value);
        public static explicit operator nuint(UInt256 value);

        public static explicit operator double(UInt256 value);
        public static explicit operator decimal(UInt256 value);
        public static explicit operator Half(UInt256 value);
        public static explicit operator float(UInt256 value);
    }
}

API Usage

var a = new UInt256(12);
var b = new UInt256(span);
var c = a + b;

Alternative Designs

No response

Risks

No response

ghost commented 1 year ago

Tagging subscribers to this area: @dotnet/area-system-numerics See info in area-owners.md if you want to be subscribed.

Issue Details
### Background and motivation 256 bit integers are becoming more commonly used with 3,189 questions on StackOverflow and use in .NET for example in the application [NethermindEth](https://github.com/NethermindEth) and library [Nethereum](https://github.com/Nethereum). While BigInteger can be used a dedicated type can provide x14 gains and much lower memory usage than BigInteger through not needing to use an arrays to represent data. The implementation can also achieve x2.5 gains using Avx2 vs a software implementation although the approach starts to become exotic https://github.com/NethermindEth/int256/pull/24 ### API Proposal ```csharp namespace System { public readonly struct Int256 : IComparable, IComparable, IEquatable, IBinaryInteger, IMinMaxValue, ISpanFormattable, ISignedNumber { // Constructors public Int256(ReadOnlySpan bytes, bool isBigEndian = false); public Int256(uint r0, uint r1, uint r2, uint r3, uint r4, uint r5, uint r6, uint r7); public Int256(ulong u0 = 0, ulong u1 = 0, ulong u2 = 0, ulong u3 = 0); public Int256(UInt128 upper, UInt128 lower); // Properties public static Int256 AdditiveIdentity { get; } public static Int256 MaxValue { get; } public static Int256 MinValue { get; } public static Int256 MultiplicativeIdentity { get; } public static Int256 NegativeOne { get; } public static Int256 One { get; } public static Int256 Zero { get; } // Addition Operators public static Int256 operator +(Int256 left, Int256 right); public static Int256 operator checked +(Int256 left, Int256 right); // Bitwise Operators public static Int256 operator &(Int256 left, Int256 right); public static Int256 operator |(Int256 left, Int256 right); public static Int256 operator ^(Int256 left, Int256 right); public static Int256 operator ~(Int256 left, Int256 right); // Comparison Operators public static bool operator <(Int256 left, Int256 right); public static bool operator <=(Int256 left, Int256 right); public static bool operator >(Int256 left, Int256 right); public static bool operator >=(Int256 left, Int256 right); // Conversion From Operators public static implicit operator Int256(byte value); public static implicit operator Int256(char value); public static implicit operator Int256(short value); public static implicit operator Int256(int value); public static implicit operator Int256(long value); public static implicit operator Int256(Int128 value); public static implicit operator Int256(nint value); public static implicit operator Int256(sbyte value); public static implicit operator Int256(ushort value); public static implicit operator Int256(uint value); public static implicit operator Int256(ulong value); public static implicit operator Int256(nuint value); public static implicit operator Int256(UInt128 value); public static explicit operator Int256(double value); public static explicit operator Int256(decimal value); public static explicit operator Int256(Half value); public static explicit operator Int256(float value); public static explicit operator Int256(UInt256 value); // Conversion To Operators public static explicit operator byte(Int256 value); public static explicit operator char(Int256 value); public static explicit operator short(Int256 value); public static explicit operator int(Int256 value); public static explicit operator long(Int256 value); public static explicit operator Int128(Int256 value); public static explicit operator nint(Int256 value); public static explicit operator sbyte(Int256 value); public static explicit operator ushort(Int256 value); public static explicit operator uint(Int256 value); public static explicit operator ulong(Int256 value); public static explicit operator nuint(Int256 value); public static explicit operator UInt128(Int256 value); public static explicit operator double(Int256 value); public static explicit operator decimal(Int256 value); public static explicit operator Half(Int256 value); public static explicit operator float(Int256 value); // Decrement Operators public static Int256 operator --(Int256 value); public static Int256 operator checked --(Int256 value); // Division Operators public static Int256 operator /(Int256 left, Int256 right); public static Int256 operator checked /(Int256 left, Int256 right); // Equality Operators public static bool operator ==(Int256 left, Int256 right); public static bool operator !=(Int256 left, Int256 right); // Increment Operators public static Int256 operator ++(Int256 value); public static Int256 operator checked ++(Int256 value); // Modulus Operators public static Int256 operator %(Int256 left, Int256 right); // Multiply Operators public static Int256 operator *(Int256 left, Int256 right); public static Int256 operator checked *(Int256 left, Int256 right); // Shift Operators public static Int256 operator <<(Int256 value, int shiftAmount); public static Int256 operator >>(Int256 value, int shiftAmount); public static Int256 operator >>>(Int256 value, int shiftAmount); // Subtraction Operators public static Int256 operator -(Int256 left, Int256 right); public static Int256 operator checked -(Int256 left, Int256 right); // Unary Negation/Plus Operators public static Int256 operator +(Int256 value); public static Int256 operator -(Int256 value); public static Int256 operator checked -(Int256 value); // Comparison Methods public int CompareTo(object? obj); public int CompareTo(Int256 other); // Equality Methods public override bool Equals([NotNullWhen(true)] object? obj); public bool Equals(Int256 other); // Hashing Methods public override int GetHashCode(); // Parsing Methods public static Int256 Parse(string s); public static Int256 Parse(string s, NumberStyles style); public static Int256 Parse(string s, IFormatProvider? provider); public static Int256 Parse(string s, NumberStyles style, IFormatProvider? provider); public static Int256 Parse(ReadOnlySpan s, IFormatProvider? provider); public static Int256 Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null); public static bool TryParse([NotNullWhen(true)] string? s, out Int256 result); public static bool TryParse(ReadOnlySpan s, out Int256 result); public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out long result); public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out Int256 result); public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, out Int256 result); public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out Int256 result); // Formatting Methods public override string ToString(); public string ToString(IFormatProvider? provider); public string ToString(string? format); public string ToString(string? format, IFormatProvider? provider); public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? provider = null); // Binary Integer Methods public static Int256 LeadingZeroCount(Int256 value); public static Int256 PopCount(Int256 value); public static Int256 RotateLeft(Int256 value); public static Int256 RotateRight(Int256 value); public static Int256 TrailingZeroCount(Int256 value); // Binary Number Methods public static bool IsPow2(Int256 value); public static Int256 Log2(Int256 value); // Number Methods public static Int256 Abs(Int256 value); public static Int256 Clamp(Int256 value, Int256 min, Int256 max); public static Int256 CreateChecked(TOther value) where TOther : INumber; public static Int256 CreateSaturating(TOther value) where TOther : INumber; public static Int256 CreateTruncating(TOther value) where TOther : INumber; public static (Int256 Quotient, Int256 Remainder) DivRem(Int256 left, Int256 right); public static Int256 Max(Int256 x, Int256 y); public static Int256 Min(Int256 x, Int256 y); public static Int256 Sign(Int256 value); public static bool TryCreate(TOther value, out Int256 result) where TOther : INumber; } public readonly struct UInt256 : IComparable, IComparable, IEquatable, IBinaryInteger, IMinMaxValue, ISpanFormattable, IUnsignedNumber { // Same members as Int256, but taking/returning UInt256 // NegativeOne is not defined/exposed // Conversion From/To operators differ as per below // Conversion From Operators public static implicit operator UInt256(byte value); public static implicit operator UInt256(char value); public static implicit operator UInt256(ushort value); public static implicit operator UInt256(uint value); public static implicit operator UInt256(ulong value); public static implicit operator UInt256(UInt128 value); public static implicit operator UInt256(nuint value); public static explicit operator UInt256(short value); public static explicit operator UInt256(int value); public static explicit operator UInt256(long value); public static explicit operator UInt256(Int128 value); public static explicit operator UInt256(nint value); public static explicit operator UInt256(sbyte value); public static explicit operator UInt256(double value); public static explicit operator UInt256(decimal value); public static explicit operator UInt256(Half value); public static explicit operator UInt256(float value); public static explicit operator UInt256(Int256 value); // Conversion To Operators public static explicit operator byte(UInt256 value); public static explicit operator char(UInt256 value); public static explicit operator short(UInt256 value); public static explicit operator int(UInt256 value); public static explicit operator long(UInt256 value); public static explicit operator Int128(UInt256 value); public static explicit operator nint(UInt256 value); public static explicit operator sbyte(UInt256 value); public static explicit operator ushort(UInt256 value); public static explicit operator uint(UInt256 value); public static explicit operator ulong(UInt256 value); public static explicit operator UInt128(UInt256 value); public static explicit operator nuint(UInt256 value); public static explicit operator double(UInt256 value); public static explicit operator decimal(UInt256 value); public static explicit operator Half(UInt256 value); public static explicit operator float(UInt256 value); } } ``` ### API Usage ```csharp var a = new UInt256(12); var b = new UInt256(span); var c = a + b; ``` ### Alternative Designs _No response_ ### Risks _No response_
Author: benaadams
Assignees: -
Labels: `api-suggestion`, `area-System.Numerics`
Milestone: -
tannergooding commented 1 year ago

This is one where I'm not convinced providing it as part of the BCL is good or necessary.

In the case of Int128/UInt128, there is a reasonable expectation that the runtime provide the types because Int128/UInt128 are often defined as "ABI primitives" with specialized rules for layout and calling convention. This means, simply put, they are not something that can be provided by an external library. This coupled with there being many cases where hardware acceleration can light up and where specialized APIs might be considered for exposure means that it was a good fit for the BCL, particularly in the context of the new generic math features that allowed it to be exposed without dedicated language support and the sheer number of requests we had gotten over the years.

However, in the case of Int256/UInt256, we really have none of those considerations. They are not ABI primitives and don't really get any "specialized APIs or optimizations" that cannot be filled by some external library. This coupled with the new language features that support generic math and the various hardware intrinsics that allow users to perform manual optimization of their types reduces this further. It's also worth noting that while ~3200 questions related to the type isn't "small", per say, it isn't necessarily representative of the feature being hugely necessary or impactful either and is nowhere near the volume of requests and asks that exist for 128-bit integers.

Because of this, I don't expect we'd be willing to expose these types as part of the BCL, and certainly not part of the System namespace, at this point in time. I'm certainly open to revisiting this in the future, seeing more data as to the usage of these types, etc. I'd also like for us to potentially explore if there are optimizations or modifications we can make to BigInteger to improve its performance and reduce the gap that exists between it and some Int256/UInt256.

tannergooding commented 1 year ago

I'd also welcome someone providing their own external implementation and providing it via a NuGet package.

And I'd like to call out, as an idea, that there are a few types people have suggested over the years, like these ones, that I can't see us providing within the BCL, but where they might benefit from having some "unofficially official" 3rd party source. If enough people are interested, I'd be willing to coordinate on creating a repository and going through the necessary steps of getting it into the .NET Foundation, etc. Such an endeavor would be "unofficial", it would be out of box, not part of dotnet/runtime, and entirely "3rd party". It would ultimately just be a centralized location for such types, extensions, or other optimized numeric algorithms and utilities. There would be a slight bonus that one of the current numerics/intrinsics area owners would be willing to help with API design considerations and code review in their spare time.

ghost commented 1 year ago

This issue has been marked needs-author-action and may be missing some important information.

Sergio0694 commented 1 year ago

@tannergooding As an option if this is something that can't go into the runtime, the .NET Community Toolkit could also be used. It's sort of "in between" in that it's not part of the runtime but it's still first party and officially supported (ie. it's published and maintained by Microsoft). It's also already part of the .NET Foundation. For instance, we could potentially experiment with adding a new "CommunityToolkit.Numerics" package (or adding APIs to an existing one), and use that as the home for APIs such as this one, Complex<T> in case it didn't get past API review, etc. 🙂

tannergooding commented 1 year ago

@Sergio0694, I appreciate the offer and it's something that might be worth exploring.

However, I'm also not convinced that's a good idea. One general issue that is worth addressing is the perception that things must be published and maintained by Microsoft. Saying it's not a right fit for the BCL and then turning around and throwing it in some other officially maintained thing doesn't make any progress towards fixing the underlying perception issues that things must be provided by Microsoft. There is also the factor that it being maintained by Microsoft implies a level of support and given many of these types may require deep domain expertise/knowledge that may not exist or be available on the team maintaining the community toolkit.

I think it would be altogether better and healthier for the .NET ecosystem for us to make progress towards something that is truly 3rd party. There would be benefit for some minimal effort around getting such projects started, and ensuring project maintainers understand the general API design rules/considerations we strive to follow in the BCL. Such projects having a relationship, of any kind, with the maintainers of the official APIs likewise benefits both sides of the board.

-- I'm thinking about this from multiple perspectives. One is from the perspective of being an official maintainer for various APIs that ship in box with .NET and understanding what likely will or will not pass API review as well as the general direction that I think would best benefit the "areas" I help maintain.

However, there is another equally important perspective from being an independent .NET OSS maintainer as well as being part of the .NET Foundation project/maintainers committees (all of which are not related to the work I do on dotnet as part of my employment).

When taking all of this into account, I don't think this is something that would pass API review at this time. However, I also see the benefit of having such an API and ensuring there is some common location people might be able to go and find this type or related types. Then accounting for the known perception issues that many people want to work towards resolving and the domain expertise required to maintain such APIs, I come to the conclusion that something completely 3rd party that is started and maintained by people passionate about this space is the right direction. Getting things setup, ensuring it still has that .NET BCL look and feel, and similar is something that I can then offer assistance on from all my perspectives.

benaadams commented 1 year ago

However, in the case of Int256/UInt256, we really have none of those considerations. They are not ABI primitives and don't really get any "specialized APIs or optimizations" that cannot be filled by some external library.

Except to be implemented well they need ADC, ADCX and ADOX which have previously been rejected as too complicated to surface and optimize https://github.com/dotnet/runtime/issues/72423

ADCX and ADOX have been introduced in combination with MULX to maintain independent carry chains so large integer multiplication can be parrallelised: Intel: New Instructions Supporting Large Integer Arithmetic and Intel: Large Integer Squaring so they cannot be easily written in C# directly (third column):

image
tannergooding commented 1 year ago

Those are cases where the JIT needs to start with recognizing the relevant non-intrinsic pattern and where we may want to revisit such a intrinsic APIs in the future, particularly with the improvements the JIT has received since the last time we looked.

tannergooding commented 1 year ago

Noting that for https://github.com/dotnet/runtime/issues/72423 in particular, we didn't reject the proposal. It was closed because there wasn't an API proposal there.

If someone opened a new proposal following the appropriate template, we could bring it to API review.

The difficult part is really in doing the JIT work and that the API shape may change slightly depending on what is "optimal" for the JIT.

benaadams commented 1 year ago

Noting that for #72423 in particular, we didn't reject the proposal. It was closed because there wasn't an API proposal there.

If someone opened a new proposal following the appropriate template, we could bring it to API review.

The difficult part is really in doing the JIT work and that the API shape may change slightly depending on what is "optimal" for the JIT.

Added proposal https://github.com/dotnet/runtime/issues/80674

SommerEngineering commented 1 year ago

Also related to #12221 because both issues involve scenarios that require large data types (for e.g. machine learning, big data / HPC, blockchains, etc.)

LukaszRozmej commented 1 year ago

We are happy to make https://github.com/NethermindEth/int256 the high performance Int256/UInt256 .net library, we plan keep working at it and happy to accept external contributions, like great work of @benaadams .

I agree that having https://github.com/dotnet/runtime/issues/80674 would be great for optimizing multiplication.