Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API Proposal]: Add AllBitsSet to the IBinaryNumber Interface #69676

Closed
dakersnar opened this issue May 23, 2022 · 2 comments · Fixed by #71356 or #72961
Closed

[API Proposal]: Add AllBitsSet to the IBinaryNumber Interface #69676

dakersnar opened this issue May 23, 2022 · 2 comments · Fixed by #71356 or #72961
Labels
api-approved API was approved in API review, it can be implemented area-System.Numerics
Milestone

Comments

@dakersnar
Copy link
Contributor

dakersnar commented May 23, 2022

Background and motivation

Conceptually, T.AllBitsSet returns an instance of the binary number type T where every bit is set to 1. For example, Int32.AllBitsSet is 0xFFFFFFFF, or -1. This concept is generally useful for masking purposes. For example, Vectors use AllBitsSet often for Conditional Select, as bitwise-anding a number with AllBitsSet will produce the same number, in contrast to bitwise-anding a number with Zero. As brought up by #60882, AllBitsSet would be a nice addition to the IBinaryNumber interface, potentially enabling future generic refactoring of Scalar<T>.

The following types would explicitly implement AllBitsSet: Double, Half, NFloat, Single, Byte, Char, Int16, Int32, Int64, IntPtr, SByte, UInt16, UInt32, UInt64, UIntPtr, BigInteger, Int128, Uint128.

Design of the implementation for all of these types is trivial except for BigInteger. For BigInteger, the most obvious implementation would be to return MinusOne, as despite the internal bit representation not being literally AllBitsSet (due to BigInteger having unbounded size), it behaves as such for bitwise operations.

API Proposal

namespace System.Numerics
{

  public partial interface IBinaryNumber<TSelf>
  {
       static abstract TSelf AllBitsSet { get; }
  }

}

API Usage

T genericAlgorithm(T input) 
where T : IBinaryNumber<T> {
    return input + T.AllBitsSet;
}

Alternative Designs

When deciding whether a method is implemented explicitly or implicitly for Generic Math, we have used the following rule: if the concept is trivially handled by knowing the concrete type, it's implemented explicitly. In other words, it is not exposed on the concrete type. This way, the implementation is only available when working with the generic interface.

In this case, we follow this logic and implement AllBitsSet explicitly, as knowing the concrete type leads to a trivial implementation (https://source.dot.net/#System.Private.CoreLib/Scalar.cs,11). However, it could be argued that AllBitsSet is conceptually tricky enough for some of these types that a implicit implementation is warranted.

Additional Notes

Currently, refactoring Scalar<T> to take advantage of this is not possible without a language change. More specifically, the language doesn't have a way to "bridge" type constraints. So, since Vector<T> is where T : struct but we'd want Scalar<T> to be where T : struct, IBinaryNumber<T>, we'd need the language to provide some way to allow Vector<T> to use Scalar<T> despite the mismatching type requirements.

@dakersnar dakersnar added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label May 23, 2022
@ghost ghost added the untriaged New issue has not been triaged by the area owner label May 23, 2022
@ghost
Copy link

ghost commented May 23, 2022

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

Conceptually, T.AllBitsSet returns an instance of the binary number type T where every bit is set to 1. For example, Int32.AllBitsSet is 0xFFFFFFFF, or -1. This concept is generally useful for masking purposes. For example, Vectors use AllBitsSet often for Conditional Select, as bitwise-anding a number with AllBitsSet will produce the same number, in contrast to bitwise-anding a number with Zero. As brought up by #60882, AllBitsSet would be a nice addition to the IBinaryNumber interface, potentially enabling future generic refactoring of Scalar<T>.

The following types would explicitly implement AllBitsSet: Double, Half, NFloat, Single, Byte, Char, Int16, Int32, Int64, IntPtr, SByte, UInt16, UInt32, UInt64, UIntPtr, BigInteger, Int128, Uint128.

Design of the implementation for all of these types is trivial except for BigInteger. For BigInteger, the most obvious implementation would be to return MinusOne, as despite the internal bit representation not being literally AllBitsSet (due to BigInteger having unbounded size), it behaves as such for bitwise operations.

API Proposal

namespace System.Numerics
{

  public partial interface IBinaryNumber<TSelf>
  {
       static abstract TSelf AllBitsSet { get; }
  }

}

API Usage

T genericAlgorithm(T input) 
where T : IBinaryNumber<T> {
    return input + T.AllBitsSet;
}

Alternative Designs

When deciding whether a method is implemented explicitly or implicitly for Generic Math, we have used the following rule: if the concept is trivially handled by knowing the concrete type, it's implemented explicitly. In other words, it is not exposed on the concrete type. This way, the implementation is only available when working with the generic interface.

In this case, we follow this logic and implement AllBitsSet explicitly, as knowing the concrete type leads to a trivial implementation (https://source.dot.net/#System.Private.CoreLib/Scalar.cs,11). However, it could be argued that AllBitsSet is conceptually tricky enough for some of these types that a implicit implementation is warranted.

Risks

Currently, refactoring Scalar<T> to take advantage of this is not possible without a language change. More specifically, the language doesn't have a way to "bridge" type constraints. So, since Vector<T> is where T : struct but we'd want Scalar<T> to be where T : struct, IBinaryNumber<T>, we'd need the language to provide some way to allow Vector<T> to use Scalar<T> despite the mismatching type requirements.

Author: dakersnar
Assignees: -
Labels:

api-suggestion, area-System.Numerics, untriaged

Milestone: -

@tannergooding tannergooding added api-ready-for-review API is ready for review, it is NOT ready for implementation and removed api-suggestion Early API idea and discussion, it is NOT ready for implementation untriaged New issue has not been triaged by the area owner labels May 23, 2022
@tannergooding tannergooding added this to the 7.0.0 milestone May 23, 2022
@dakersnar dakersnar added the blocking Marks issues that we want to fast track in order to unblock other important work label May 27, 2022
@bartonjs
Copy link
Member

bartonjs commented May 31, 2022

Video

  • Looks good as proposed
  • Consider DIMming it as ~Zero
namespace System.Numerics
{
    public partial interface IBinaryNumber<TSelf>
    {
        static abstract TSelf AllBitsSet { get; }
    }
}

@bartonjs bartonjs added api-approved API was approved in API review, it can be implemented and removed blocking Marks issues that we want to fast track in order to unblock other important work api-ready-for-review API is ready for review, it is NOT ready for implementation labels May 31, 2022
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jun 27, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Jun 29, 2022
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jul 27, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Aug 12, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Sep 12, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved API was approved in API review, it can be implemented area-System.Numerics
Projects
None yet
3 participants