From d75e57d76411a3c71169c8c53a327c33a9c4f598 Mon Sep 17 00:00:00 2001 From: Simon Cropp Date: Wed, 12 Aug 2026 21:57:59 +1000 Subject: [PATCH] Add BitOperations.IsPow2 polyfill (#575) Recreates System.Numerics.BitOperations on targets before netcoreapp3.0, and adds the missing IsPow2 overloads as static extension members where the type exists but the overloads do not (IsPow2 landed in net6.0, its nint/nuint overloads in net7.0). --- apiCount.include.md | 18 ++--- api_list.include.md | 10 +++ assemblySize.include.md | 32 ++++---- readme.md | 64 +++++++++------- src/ApiBuilderTests/BuildApiTest.cs | 1 + src/Consume/Consume.cs | 8 ++ src/Polyfill/BitOperations.cs | 74 +++++++++++++++++++ src/Polyfill/BitOperationsIsPow2.cs | 71 ++++++++++++++++++ src/Split/net10.0/TypeForwardeds.cs | 1 + src/Split/net11.0/TypeForwardeds.cs | 1 + src/Split/net461/BitOperations.cs | 56 ++++++++++++++ src/Split/net462/BitOperations.cs | 56 ++++++++++++++ src/Split/net47/BitOperations.cs | 56 ++++++++++++++ src/Split/net471/BitOperations.cs | 56 ++++++++++++++ src/Split/net472/BitOperations.cs | 56 ++++++++++++++ src/Split/net48/BitOperations.cs | 56 ++++++++++++++ src/Split/net481/BitOperations.cs | 56 ++++++++++++++ src/Split/net5.0/BitOperationsIsPow2.cs | 47 ++++++++++++ src/Split/net5.0/TypeForwardeds.cs | 1 + src/Split/net6.0/BitOperationsIsPow2.cs | 23 ++++++ src/Split/net6.0/TypeForwardeds.cs | 1 + src/Split/net7.0/TypeForwardeds.cs | 1 + src/Split/net8.0/TypeForwardeds.cs | 1 + src/Split/net9.0/TypeForwardeds.cs | 1 + src/Split/netcoreapp2.0/BitOperations.cs | 56 ++++++++++++++ src/Split/netcoreapp2.1/BitOperations.cs | 56 ++++++++++++++ src/Split/netcoreapp2.2/BitOperations.cs | 56 ++++++++++++++ .../netcoreapp3.0/BitOperationsIsPow2.cs | 47 ++++++++++++ src/Split/netcoreapp3.0/TypeForwardeds.cs | 1 + .../netcoreapp3.1/BitOperationsIsPow2.cs | 47 ++++++++++++ src/Split/netcoreapp3.1/TypeForwardeds.cs | 1 + src/Split/netstandard2.0/BitOperations.cs | 56 ++++++++++++++ src/Split/netstandard2.1/BitOperations.cs | 56 ++++++++++++++ src/Split/uap10.0/BitOperations.cs | 56 ++++++++++++++ src/Tests/PolyfillTests_BitOperations.cs | 69 +++++++++++++++++ 35 files changed, 1196 insertions(+), 52 deletions(-) create mode 100644 src/Polyfill/BitOperations.cs create mode 100644 src/Polyfill/BitOperationsIsPow2.cs create mode 100644 src/Split/net461/BitOperations.cs create mode 100644 src/Split/net462/BitOperations.cs create mode 100644 src/Split/net47/BitOperations.cs create mode 100644 src/Split/net471/BitOperations.cs create mode 100644 src/Split/net472/BitOperations.cs create mode 100644 src/Split/net48/BitOperations.cs create mode 100644 src/Split/net481/BitOperations.cs create mode 100644 src/Split/net5.0/BitOperationsIsPow2.cs create mode 100644 src/Split/net6.0/BitOperationsIsPow2.cs create mode 100644 src/Split/netcoreapp2.0/BitOperations.cs create mode 100644 src/Split/netcoreapp2.1/BitOperations.cs create mode 100644 src/Split/netcoreapp2.2/BitOperations.cs create mode 100644 src/Split/netcoreapp3.0/BitOperationsIsPow2.cs create mode 100644 src/Split/netcoreapp3.1/BitOperationsIsPow2.cs create mode 100644 src/Split/netstandard2.0/BitOperations.cs create mode 100644 src/Split/netstandard2.1/BitOperations.cs create mode 100644 src/Split/uap10.0/BitOperations.cs create mode 100644 src/Tests/PolyfillTests_BitOperations.cs diff --git a/apiCount.include.md b/apiCount.include.md index a163cc71..41ee45b3 100644 --- a/apiCount.include.md +++ b/apiCount.include.md @@ -1,4 +1,4 @@ -**API count: 1025** +**API count: 1031** ### Per Target Framework @@ -12,17 +12,17 @@ | `net48` | 966 | | `net481` | 966 | | `netstandard2.0` | 968 | -| `netstandard2.1` | 820 | +| `netstandard2.1` | 821 | | `netcoreapp2.0` | 891 | | `netcoreapp2.1` | 832 | | `netcoreapp2.2` | 832 | -| `netcoreapp3.0` | 778 | -| `netcoreapp3.1` | 777 | -| `net5.0` | 649 | -| `net6.0` | 554 | -| `net7.0` | 401 | -| `net8.0` | 282 | -| `net9.0` | 188 | +| `netcoreapp3.0` | 779 | +| `netcoreapp3.1` | 778 | +| `net5.0` | 650 | +| `net6.0` | 555 | +| `net7.0` | 402 | +| `net8.0` | 283 | +| `net9.0` | 189 | | `net10.0` | 135 | | `net11.0` | 58 | | `uap10.0` | 958 | diff --git a/api_list.include.md b/api_list.include.md index f7656788..6bf1aa6d 100644 --- a/api_list.include.md +++ b/api_list.include.md @@ -1477,6 +1477,16 @@ * Note: When growing, new elements are default(T); the BCL exposes uninitialized data. +#### BitOperations + + * `bool IsPow2(int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-int32)) + * `bool IsPow2(long)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-int64)) + * `bool IsPow2(nint)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-intptr)) + * `bool IsPow2(nuint)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-uintptr)) + * `bool IsPow2(uint)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-uint32)) + * `bool IsPow2(ulong)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-uint64)) + + #### CryptographicOperations * `bool FixedTimeEquals(ReadOnlySpan, byte)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptographicoperations.fixedtimeequals?view=net-11.0#system-security-cryptography-cryptographicoperations-fixedtimeequals(system-readonlyspan((system-byte))-system-byte)) diff --git a/assemblySize.include.md b/assemblySize.include.md index a540f6a9..dd4f2db9 100644 --- a/assemblySize.include.md +++ b/assemblySize.include.md @@ -3,7 +3,7 @@ | | Empty Assembly | With Polyfill | Diff | Ensure | ArgumentExceptions | StringInterpolation | Nullability | |----------------|----------------|---------------|-----------|-----------|--------------------|---------------------|-------------| | netstandard2.0 | 8.0KB | 358.5KB | +350.5KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | -| netstandard2.1 | 8.5KB | 312.0KB | +303.5KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | +| netstandard2.1 | 8.5KB | 312.5KB | +304.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | | net461 | 8.5KB | 357.0KB | +348.5KB | +7.5KB | +6.5KB | +8.0KB | +12.5KB | | net462 | 7.0KB | 360.5KB | +353.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | | net47 | 7.0KB | 360.5KB | +353.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | @@ -14,13 +14,13 @@ | netcoreapp2.0 | 9.0KB | 336.0KB | +327.0KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | | netcoreapp2.1 | 9.0KB | 316.0KB | +307.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | | netcoreapp2.2 | 9.0KB | 316.0KB | +307.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| netcoreapp3.0 | 9.5KB | 308.5KB | +299.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| netcoreapp3.1 | 9.5KB | 306.5KB | +297.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | -| net5.0 | 9.5KB | 270.5KB | +261.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | -| net6.0 | 10.0KB | 212.0KB | +202.0KB | +10.0KB | +7.0KB | +1.0KB | +3.5KB | -| net7.0 | 10.0KB | 174.5KB | +164.5KB | +12.0KB | +5.5KB | +512bytes | +3.5KB | -| net8.0 | 9.5KB | 145.0KB | +135.5KB | +8.5KB | +512bytes | +512bytes | +3.5KB | -| net9.0 | 9.5KB | 98.0KB | +88.5KB | +8.5KB | | +512bytes | +3.5KB | +| netcoreapp3.0 | 9.5KB | 308.5KB | +299.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | +| netcoreapp3.1 | 9.5KB | 307.0KB | +297.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net5.0 | 9.5KB | 271.0KB | +261.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net6.0 | 10.0KB | 212.5KB | +202.5KB | +10.0KB | +7.0KB | +512bytes | +3.5KB | +| net7.0 | 10.0KB | 175.0KB | +165.0KB | +11.5KB | +8.0KB | +512bytes | +3.0KB | +| net8.0 | 9.5KB | 145.5KB | +136.0KB | +8.5KB | | +512bytes | +3.0KB | +| net9.0 | 9.5KB | 98.5KB | +89.0KB | +8.5KB | | +512bytes | +3.5KB | | net10.0 | 10.0KB | 76.0KB | +66.0KB | +8.5KB | | +512bytes | +3.5KB | | net11.0 | 10.0KB | 20.5KB | +10.5KB | +9.0KB | | +512bytes | +3.5KB | @@ -30,7 +30,7 @@ | | Empty Assembly | With Polyfill | Diff | Ensure | ArgumentExceptions | StringInterpolation | Nullability | |----------------|----------------|---------------|-----------|-----------|--------------------|---------------------|-------------| | netstandard2.0 | 8.0KB | 524.4KB | +516.4KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | -| netstandard2.1 | 8.5KB | 450.9KB | +442.4KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | +| netstandard2.1 | 8.5KB | 451.8KB | +443.3KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | | net461 | 8.5KB | 524.0KB | +515.5KB | +15.2KB | +8.2KB | +12.9KB | +17.9KB | | net462 | 7.0KB | 527.5KB | +520.5KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | | net47 | 7.0KB | 527.2KB | +520.2KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | @@ -41,12 +41,12 @@ | netcoreapp2.0 | 9.0KB | 491.3KB | +482.3KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | | netcoreapp2.1 | 9.0KB | 459.0KB | +450.0KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | | netcoreapp2.2 | 9.0KB | 459.0KB | +450.0KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| netcoreapp3.0 | 9.5KB | 442.3KB | +432.8KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| netcoreapp3.1 | 9.5KB | 440.3KB | +430.8KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | -| net5.0 | 9.5KB | 386.1KB | +376.6KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | -| net6.0 | 10.0KB | 307.5KB | +297.5KB | +17.7KB | +8.7KB | +1.6KB | +4.2KB | -| net7.0 | 10.0KB | 251.4KB | +241.4KB | +19.6KB | +6.9KB | +1.1KB | +4.2KB | -| net8.0 | 9.5KB | 206.4KB | +196.9KB | +16.0KB | +811bytes | +1.1KB | +4.2KB | -| net9.0 | 9.5KB | 138.3KB | +128.8KB | +16.0KB | | +1.1KB | +4.2KB | +| netcoreapp3.0 | 9.5KB | 442.7KB | +433.2KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | +| netcoreapp3.1 | 9.5KB | 441.2KB | +431.7KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net5.0 | 9.5KB | 387.0KB | +377.5KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net6.0 | 10.0KB | 308.4KB | +298.4KB | +17.7KB | +8.7KB | +1.1KB | +4.2KB | +| net7.0 | 10.0KB | 252.3KB | +242.3KB | +19.1KB | +9.4KB | +1.1KB | +3.7KB | +| net8.0 | 9.5KB | 207.3KB | +197.8KB | +16.0KB | +299bytes | +1.1KB | +3.7KB | +| net9.0 | 9.5KB | 139.1KB | +129.6KB | +16.0KB | | +1.1KB | +4.2KB | | net10.0 | 10.0KB | 108.0KB | +98.0KB | +16.0KB | | +1.1KB | +4.2KB | | net11.0 | 10.0KB | 30.3KB | +20.3KB | +16.5KB | | +1.1KB | +4.2KB | diff --git a/readme.md b/readme.md index 6250af7d..828151bb 100644 --- a/readme.md +++ b/readme.md @@ -13,7 +13,7 @@ The package targets `netstandard2.0` and is designed to support the following ru * `uap10` -**API count: 1025** +**API count: 1031** ### Per Target Framework @@ -27,17 +27,17 @@ The package targets `netstandard2.0` and is designed to support the following ru | `net48` | 966 | | `net481` | 966 | | `netstandard2.0` | 968 | -| `netstandard2.1` | 820 | +| `netstandard2.1` | 821 | | `netcoreapp2.0` | 891 | | `netcoreapp2.1` | 832 | | `netcoreapp2.2` | 832 | -| `netcoreapp3.0` | 778 | -| `netcoreapp3.1` | 777 | -| `net5.0` | 649 | -| `net6.0` | 554 | -| `net7.0` | 401 | -| `net8.0` | 282 | -| `net9.0` | 188 | +| `netcoreapp3.0` | 779 | +| `netcoreapp3.1` | 778 | +| `net5.0` | 650 | +| `net6.0` | 555 | +| `net7.0` | 402 | +| `net8.0` | 283 | +| `net9.0` | 189 | | `net10.0` | 135 | | `net11.0` | 58 | | `uap10.0` | 958 | @@ -97,7 +97,7 @@ This project uses features from the newest stable SDK and C# language. As such c | | Empty Assembly | With Polyfill | Diff | Ensure | ArgumentExceptions | StringInterpolation | Nullability | |----------------|----------------|---------------|-----------|-----------|--------------------|---------------------|-------------| | netstandard2.0 | 8.0KB | 358.5KB | +350.5KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | -| netstandard2.1 | 8.5KB | 312.0KB | +303.5KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | +| netstandard2.1 | 8.5KB | 312.5KB | +304.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | | net461 | 8.5KB | 357.0KB | +348.5KB | +7.5KB | +6.5KB | +8.0KB | +12.5KB | | net462 | 7.0KB | 360.5KB | +353.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | | net47 | 7.0KB | 360.5KB | +353.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | @@ -108,13 +108,13 @@ This project uses features from the newest stable SDK and C# language. As such c | netcoreapp2.0 | 9.0KB | 336.0KB | +327.0KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | | netcoreapp2.1 | 9.0KB | 316.0KB | +307.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | | netcoreapp2.2 | 9.0KB | 316.0KB | +307.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| netcoreapp3.0 | 9.5KB | 308.5KB | +299.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| netcoreapp3.1 | 9.5KB | 306.5KB | +297.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | -| net5.0 | 9.5KB | 270.5KB | +261.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | -| net6.0 | 10.0KB | 212.0KB | +202.0KB | +10.0KB | +7.0KB | +1.0KB | +3.5KB | -| net7.0 | 10.0KB | 174.5KB | +164.5KB | +12.0KB | +5.5KB | +512bytes | +3.5KB | -| net8.0 | 9.5KB | 145.0KB | +135.5KB | +8.5KB | +512bytes | +512bytes | +3.5KB | -| net9.0 | 9.5KB | 98.0KB | +88.5KB | +8.5KB | | +512bytes | +3.5KB | +| netcoreapp3.0 | 9.5KB | 308.5KB | +299.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | +| netcoreapp3.1 | 9.5KB | 307.0KB | +297.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net5.0 | 9.5KB | 271.0KB | +261.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net6.0 | 10.0KB | 212.5KB | +202.5KB | +10.0KB | +7.0KB | +512bytes | +3.5KB | +| net7.0 | 10.0KB | 175.0KB | +165.0KB | +11.5KB | +8.0KB | +512bytes | +3.0KB | +| net8.0 | 9.5KB | 145.5KB | +136.0KB | +8.5KB | | +512bytes | +3.0KB | +| net9.0 | 9.5KB | 98.5KB | +89.0KB | +8.5KB | | +512bytes | +3.5KB | | net10.0 | 10.0KB | 76.0KB | +66.0KB | +8.5KB | | +512bytes | +3.5KB | | net11.0 | 10.0KB | 20.5KB | +10.5KB | +9.0KB | | +512bytes | +3.5KB | @@ -124,7 +124,7 @@ This project uses features from the newest stable SDK and C# language. As such c | | Empty Assembly | With Polyfill | Diff | Ensure | ArgumentExceptions | StringInterpolation | Nullability | |----------------|----------------|---------------|-----------|-----------|--------------------|---------------------|-------------| | netstandard2.0 | 8.0KB | 524.4KB | +516.4KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | -| netstandard2.1 | 8.5KB | 450.9KB | +442.4KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | +| netstandard2.1 | 8.5KB | 451.8KB | +443.3KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | | net461 | 8.5KB | 524.0KB | +515.5KB | +15.2KB | +8.2KB | +12.9KB | +17.9KB | | net462 | 7.0KB | 527.5KB | +520.5KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | | net47 | 7.0KB | 527.2KB | +520.2KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | @@ -135,13 +135,13 @@ This project uses features from the newest stable SDK and C# language. As such c | netcoreapp2.0 | 9.0KB | 491.3KB | +482.3KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | | netcoreapp2.1 | 9.0KB | 459.0KB | +450.0KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | | netcoreapp2.2 | 9.0KB | 459.0KB | +450.0KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| netcoreapp3.0 | 9.5KB | 442.3KB | +432.8KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| netcoreapp3.1 | 9.5KB | 440.3KB | +430.8KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | -| net5.0 | 9.5KB | 386.1KB | +376.6KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | -| net6.0 | 10.0KB | 307.5KB | +297.5KB | +17.7KB | +8.7KB | +1.6KB | +4.2KB | -| net7.0 | 10.0KB | 251.4KB | +241.4KB | +19.6KB | +6.9KB | +1.1KB | +4.2KB | -| net8.0 | 9.5KB | 206.4KB | +196.9KB | +16.0KB | +811bytes | +1.1KB | +4.2KB | -| net9.0 | 9.5KB | 138.3KB | +128.8KB | +16.0KB | | +1.1KB | +4.2KB | +| netcoreapp3.0 | 9.5KB | 442.7KB | +433.2KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | +| netcoreapp3.1 | 9.5KB | 441.2KB | +431.7KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net5.0 | 9.5KB | 387.0KB | +377.5KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net6.0 | 10.0KB | 308.4KB | +298.4KB | +17.7KB | +8.7KB | +1.1KB | +4.2KB | +| net7.0 | 10.0KB | 252.3KB | +242.3KB | +19.1KB | +9.4KB | +1.1KB | +3.7KB | +| net8.0 | 9.5KB | 207.3KB | +197.8KB | +16.0KB | +299bytes | +1.1KB | +3.7KB | +| net9.0 | 9.5KB | 139.1KB | +129.6KB | +16.0KB | | +1.1KB | +4.2KB | | net10.0 | 10.0KB | 108.0KB | +98.0KB | +16.0KB | | +1.1KB | +4.2KB | | net11.0 | 10.0KB | 30.3KB | +20.3KB | +16.5KB | | +1.1KB | +4.2KB | @@ -2008,6 +2008,16 @@ The class `Polyfill` includes the following extension methods: * Note: When growing, new elements are default(T); the BCL exposes uninitialized data. +#### BitOperations + + * `bool IsPow2(int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-int32)) + * `bool IsPow2(long)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-int64)) + * `bool IsPow2(nint)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-intptr)) + * `bool IsPow2(nuint)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-uintptr)) + * `bool IsPow2(uint)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-uint32)) + * `bool IsPow2(ulong)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-uint64)) + + #### CryptographicOperations * `bool FixedTimeEquals(ReadOnlySpan, byte)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptographicoperations.fixedtimeequals?view=net-11.0#system-security-cryptography-cryptographicoperations-fixedtimeequals(system-readonlyspan((system-byte))-system-byte)) @@ -2257,7 +2267,7 @@ void ObjectDisposedExceptionExample(bool isDisposed) ObjectDisposedException.ThrowIf(isDisposed, typeof(Consume)); } ``` -snippet source | anchor +snippet source | anchor @@ -2276,7 +2286,7 @@ void EnsureExample(Order order, Customer customer, string customerId, string ema this.quantity = Ensure.NotNegativeOrZero(quantity); } ``` -snippet source | anchor +snippet source | anchor diff --git a/src/ApiBuilderTests/BuildApiTest.cs b/src/ApiBuilderTests/BuildApiTest.cs index 77d97df2..42fc1098 100644 --- a/src/ApiBuilderTests/BuildApiTest.cs +++ b/src/ApiBuilderTests/BuildApiTest.cs @@ -19,6 +19,7 @@ public Task RunWithRoslyn() WriteHelper("Lock", writer, ref count); WriteHelper(nameof(KeyValuePair), writer, ref count); WriteHelper("CollectionsMarshal", writer, ref count); + WriteHelper("BitOperations", writer, ref count); WriteHelper("CryptographicOperations", writer, ref count); WriteHelper("Utf16", writer, ref count); WriteType(nameof(TaskCompletionSource), writer, ref count); diff --git a/src/Consume/Consume.cs b/src/Consume/Consume.cs index 52c5f94b..267d3e89 100644 --- a/src/Consume/Consume.cs +++ b/src/Consume/Consume.cs @@ -27,6 +27,7 @@ namespace Consumes; using System.IO.Compression; using System.Linq; using System.Net.Http; +using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; @@ -134,6 +135,13 @@ class Consume var collectionsMarshalSpan = CollectionsMarshal.AsSpan(collectionsMarshalList); #endif + var isPow2Int = BitOperations.IsPow2(8); + var isPow2Uint = BitOperations.IsPow2(8u); + var isPow2Long = BitOperations.IsPow2(8L); + var isPow2Ulong = BitOperations.IsPow2(8ul); + var isPow2Nint = BitOperations.IsPow2((nint) 8); + var isPow2Nuint = BitOperations.IsPow2((nuint) 8); + var (key, value) = KeyValuePair.Create("a", "b"); #if NET6_0_OR_GREATER diff --git a/src/Polyfill/BitOperations.cs b/src/Polyfill/BitOperations.cs new file mode 100644 index 00000000..75dfb542 --- /dev/null +++ b/src/Polyfill/BitOperations.cs @@ -0,0 +1,74 @@ +#pragma warning disable + +#if !NETCOREAPP3_0_OR_GREATER + +namespace System.Numerics; + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-int32) + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + + /// + /// Evaluates whether the specified value is a power of two. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-uint32) + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + + /// + /// Evaluates whether the specified value is a power of two. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-int64) + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + + /// + /// Evaluates whether the specified value is a power of two. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-uint64) + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + + /// + /// Determines whether the specified value is a power of 2. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-intptr) + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + + /// + /// Determines whether the specified value is a power of 2. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-uintptr) + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} + +#else +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Numerics.BitOperations))] +#endif diff --git a/src/Polyfill/BitOperationsIsPow2.cs b/src/Polyfill/BitOperationsIsPow2.cs new file mode 100644 index 00000000..9b924cfa --- /dev/null +++ b/src/Polyfill/BitOperationsIsPow2.cs @@ -0,0 +1,71 @@ +#pragma warning disable + +// BitOperations exists in the BCL from netcoreapp3.0, but IsPow2 was added in net6.0 +// and its nint/nuint overloads in net7.0. Where the type is present but an overload is +// missing, the overload is added as a static extension member. For earlier targets all +// the overloads live on the recreated type in BitOperations.cs. +#if NETCOREAPP3_0_OR_GREATER && !NET7_0_OR_GREATER + +namespace Polyfills; + +using System.Numerics; + +static partial class Polyfill +{ + extension(BitOperations) + { +#if !NET6_0_OR_GREATER + + /// + /// Evaluates whether the specified value is a power of two. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-int32) + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + + /// + /// Evaluates whether the specified value is a power of two. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-uint32) + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + + /// + /// Evaluates whether the specified value is a power of two. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-int64) + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + + /// + /// Evaluates whether the specified value is a power of two. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-uint64) + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + +#endif + + /// + /// Determines whether the specified value is a power of 2. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-intptr) + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + + /// + /// Determines whether the specified value is a power of 2. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.bitoperations.ispow2?view=net-11.0#system-numerics-bitoperations-ispow2(system-uintptr) + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; + } +} + +#endif diff --git a/src/Split/net10.0/TypeForwardeds.cs b/src/Split/net10.0/TypeForwardeds.cs index 8cfaee14..cd4dd06b 100644 --- a/src/Split/net10.0/TypeForwardeds.cs +++ b/src/Split/net10.0/TypeForwardeds.cs @@ -2,6 +2,7 @@ #pragma warning disable using System.Runtime.CompilerServices; [assembly: TypeForwardedTo(typeof(System.Buffers.Text.Base64Url))] +[assembly: TypeForwardedTo(typeof(System.Numerics.BitOperations))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CollectionBuilderAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.CollectionsMarshal))] diff --git a/src/Split/net11.0/TypeForwardeds.cs b/src/Split/net11.0/TypeForwardeds.cs index 149498e3..f93df98b 100644 --- a/src/Split/net11.0/TypeForwardeds.cs +++ b/src/Split/net11.0/TypeForwardeds.cs @@ -2,6 +2,7 @@ #pragma warning disable using System.Runtime.CompilerServices; [assembly: TypeForwardedTo(typeof(System.Buffers.Text.Base64Url))] +[assembly: TypeForwardedTo(typeof(System.Numerics.BitOperations))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CollectionBuilderAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.CollectionsMarshal))] diff --git a/src/Split/net461/BitOperations.cs b/src/Split/net461/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/net461/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Split/net462/BitOperations.cs b/src/Split/net462/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/net462/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Split/net47/BitOperations.cs b/src/Split/net47/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/net47/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Split/net471/BitOperations.cs b/src/Split/net471/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/net471/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Split/net472/BitOperations.cs b/src/Split/net472/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/net472/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Split/net48/BitOperations.cs b/src/Split/net48/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/net48/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Split/net481/BitOperations.cs b/src/Split/net481/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/net481/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Split/net5.0/BitOperationsIsPow2.cs b/src/Split/net5.0/BitOperationsIsPow2.cs new file mode 100644 index 00000000..17383a81 --- /dev/null +++ b/src/Split/net5.0/BitOperationsIsPow2.cs @@ -0,0 +1,47 @@ +// +#pragma warning disable +#pragma warning disable +namespace Polyfills; +using System.Numerics; +static partial class Polyfill +{ + extension(BitOperations) + { + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; + } +} diff --git a/src/Split/net5.0/TypeForwardeds.cs b/src/Split/net5.0/TypeForwardeds.cs index d5dc2b38..eafd698b 100644 --- a/src/Split/net5.0/TypeForwardeds.cs +++ b/src/Split/net5.0/TypeForwardeds.cs @@ -1,6 +1,7 @@ // #pragma warning disable using System.Runtime.CompilerServices; +[assembly: TypeForwardedTo(typeof(System.Numerics.BitOperations))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.CollectionsMarshal))] [assembly: TypeForwardedTo(typeof(System.Security.Cryptography.CryptographicOperations))] diff --git a/src/Split/net6.0/BitOperationsIsPow2.cs b/src/Split/net6.0/BitOperationsIsPow2.cs new file mode 100644 index 00000000..bf26553a --- /dev/null +++ b/src/Split/net6.0/BitOperationsIsPow2.cs @@ -0,0 +1,23 @@ +// +#pragma warning disable +#pragma warning disable +namespace Polyfills; +using System.Numerics; +static partial class Polyfill +{ + extension(BitOperations) + { + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; + } +} diff --git a/src/Split/net6.0/TypeForwardeds.cs b/src/Split/net6.0/TypeForwardeds.cs index f04df8cf..37a8e7d7 100644 --- a/src/Split/net6.0/TypeForwardeds.cs +++ b/src/Split/net6.0/TypeForwardeds.cs @@ -1,6 +1,7 @@ // #pragma warning disable using System.Runtime.CompilerServices; +[assembly: TypeForwardedTo(typeof(System.Numerics.BitOperations))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.CollectionsMarshal))] [assembly: TypeForwardedTo(typeof(System.Security.Cryptography.CryptographicOperations))] diff --git a/src/Split/net7.0/TypeForwardeds.cs b/src/Split/net7.0/TypeForwardeds.cs index 780f168c..efb09098 100644 --- a/src/Split/net7.0/TypeForwardeds.cs +++ b/src/Split/net7.0/TypeForwardeds.cs @@ -1,6 +1,7 @@ // #pragma warning disable using System.Runtime.CompilerServices; +[assembly: TypeForwardedTo(typeof(System.Numerics.BitOperations))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.CollectionsMarshal))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute))] diff --git a/src/Split/net8.0/TypeForwardeds.cs b/src/Split/net8.0/TypeForwardeds.cs index b511da9e..f90cc3d6 100644 --- a/src/Split/net8.0/TypeForwardeds.cs +++ b/src/Split/net8.0/TypeForwardeds.cs @@ -1,6 +1,7 @@ // #pragma warning disable using System.Runtime.CompilerServices; +[assembly: TypeForwardedTo(typeof(System.Numerics.BitOperations))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CollectionBuilderAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.CollectionsMarshal))] diff --git a/src/Split/net9.0/TypeForwardeds.cs b/src/Split/net9.0/TypeForwardeds.cs index db89f0fa..002bf769 100644 --- a/src/Split/net9.0/TypeForwardeds.cs +++ b/src/Split/net9.0/TypeForwardeds.cs @@ -2,6 +2,7 @@ #pragma warning disable using System.Runtime.CompilerServices; [assembly: TypeForwardedTo(typeof(System.Buffers.Text.Base64Url))] +[assembly: TypeForwardedTo(typeof(System.Numerics.BitOperations))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CollectionBuilderAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.CollectionsMarshal))] diff --git a/src/Split/netcoreapp2.0/BitOperations.cs b/src/Split/netcoreapp2.0/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/netcoreapp2.0/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Split/netcoreapp2.1/BitOperations.cs b/src/Split/netcoreapp2.1/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/netcoreapp2.1/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Split/netcoreapp2.2/BitOperations.cs b/src/Split/netcoreapp2.2/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/netcoreapp2.2/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Split/netcoreapp3.0/BitOperationsIsPow2.cs b/src/Split/netcoreapp3.0/BitOperationsIsPow2.cs new file mode 100644 index 00000000..17383a81 --- /dev/null +++ b/src/Split/netcoreapp3.0/BitOperationsIsPow2.cs @@ -0,0 +1,47 @@ +// +#pragma warning disable +#pragma warning disable +namespace Polyfills; +using System.Numerics; +static partial class Polyfill +{ + extension(BitOperations) + { + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; + } +} diff --git a/src/Split/netcoreapp3.0/TypeForwardeds.cs b/src/Split/netcoreapp3.0/TypeForwardeds.cs index 98847ca2..21404082 100644 --- a/src/Split/netcoreapp3.0/TypeForwardeds.cs +++ b/src/Split/netcoreapp3.0/TypeForwardeds.cs @@ -1,6 +1,7 @@ // #pragma warning disable using System.Runtime.CompilerServices; +[assembly: TypeForwardedTo(typeof(System.Numerics.BitOperations))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))] [assembly: TypeForwardedTo(typeof(System.Security.Cryptography.CryptographicOperations))] [assembly: TypeForwardedTo(typeof(System.IO.EnumerationOptions))] diff --git a/src/Split/netcoreapp3.1/BitOperationsIsPow2.cs b/src/Split/netcoreapp3.1/BitOperationsIsPow2.cs new file mode 100644 index 00000000..17383a81 --- /dev/null +++ b/src/Split/netcoreapp3.1/BitOperationsIsPow2.cs @@ -0,0 +1,47 @@ +// +#pragma warning disable +#pragma warning disable +namespace Polyfills; +using System.Numerics; +static partial class Polyfill +{ + extension(BitOperations) + { + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; + } +} diff --git a/src/Split/netcoreapp3.1/TypeForwardeds.cs b/src/Split/netcoreapp3.1/TypeForwardeds.cs index 98847ca2..21404082 100644 --- a/src/Split/netcoreapp3.1/TypeForwardeds.cs +++ b/src/Split/netcoreapp3.1/TypeForwardeds.cs @@ -1,6 +1,7 @@ // #pragma warning disable using System.Runtime.CompilerServices; +[assembly: TypeForwardedTo(typeof(System.Numerics.BitOperations))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))] [assembly: TypeForwardedTo(typeof(System.Security.Cryptography.CryptographicOperations))] [assembly: TypeForwardedTo(typeof(System.IO.EnumerationOptions))] diff --git a/src/Split/netstandard2.0/BitOperations.cs b/src/Split/netstandard2.0/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/netstandard2.0/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Split/netstandard2.1/BitOperations.cs b/src/Split/netstandard2.1/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/netstandard2.1/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Split/uap10.0/BitOperations.cs b/src/Split/uap10.0/BitOperations.cs new file mode 100644 index 00000000..31b4feed --- /dev/null +++ b/src/Split/uap10.0/BitOperations.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +#pragma warning disable +namespace System.Numerics; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +/// +/// Utility methods for intrinsic bit-twiddling operations. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +static class BitOperations +{ + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(int value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(uint value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(long value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Evaluates whether the specified value is a power of two. + /// + public static bool IsPow2(ulong value) => + (value & (value - 1)) == 0 && + value != 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nint value) => + (value & (value - 1)) == 0 && + value > 0; + /// + /// Determines whether the specified value is a power of 2. + /// + public static bool IsPow2(nuint value) => + (value & (value - 1)) == 0 && + value != 0; +} diff --git a/src/Tests/PolyfillTests_BitOperations.cs b/src/Tests/PolyfillTests_BitOperations.cs new file mode 100644 index 00000000..24308870 --- /dev/null +++ b/src/Tests/PolyfillTests_BitOperations.cs @@ -0,0 +1,69 @@ +using System.Numerics; + +partial class PolyfillTests +{ + [Test] + public async Task BitOperations_IsPow2Int() + { + await Assert.That(BitOperations.IsPow2(1)).IsTrue(); + await Assert.That(BitOperations.IsPow2(2)).IsTrue(); + await Assert.That(BitOperations.IsPow2(1 << 30)).IsTrue(); + await Assert.That(BitOperations.IsPow2(0)).IsFalse(); + await Assert.That(BitOperations.IsPow2(3)).IsFalse(); + await Assert.That(BitOperations.IsPow2(-2)).IsFalse(); + await Assert.That(BitOperations.IsPow2(int.MinValue)).IsFalse(); + await Assert.That(BitOperations.IsPow2(int.MaxValue)).IsFalse(); + } + + [Test] + public async Task BitOperations_IsPow2Uint() + { + await Assert.That(BitOperations.IsPow2(1u)).IsTrue(); + await Assert.That(BitOperations.IsPow2(2u)).IsTrue(); + await Assert.That(BitOperations.IsPow2(1u << 31)).IsTrue(); + await Assert.That(BitOperations.IsPow2(0u)).IsFalse(); + await Assert.That(BitOperations.IsPow2(3u)).IsFalse(); + await Assert.That(BitOperations.IsPow2(uint.MaxValue)).IsFalse(); + } + + [Test] + public async Task BitOperations_IsPow2Long() + { + await Assert.That(BitOperations.IsPow2(1L)).IsTrue(); + await Assert.That(BitOperations.IsPow2(1L << 62)).IsTrue(); + await Assert.That(BitOperations.IsPow2(0L)).IsFalse(); + await Assert.That(BitOperations.IsPow2(3L)).IsFalse(); + await Assert.That(BitOperations.IsPow2(-2L)).IsFalse(); + await Assert.That(BitOperations.IsPow2(long.MinValue)).IsFalse(); + await Assert.That(BitOperations.IsPow2(long.MaxValue)).IsFalse(); + } + + [Test] + public async Task BitOperations_IsPow2Ulong() + { + await Assert.That(BitOperations.IsPow2(1ul)).IsTrue(); + await Assert.That(BitOperations.IsPow2(1ul << 63)).IsTrue(); + await Assert.That(BitOperations.IsPow2(0ul)).IsFalse(); + await Assert.That(BitOperations.IsPow2(3ul)).IsFalse(); + await Assert.That(BitOperations.IsPow2(ulong.MaxValue)).IsFalse(); + } + + [Test] + public async Task BitOperations_IsPow2Nint() + { + await Assert.That(BitOperations.IsPow2((nint) 1)).IsTrue(); + await Assert.That(BitOperations.IsPow2((nint) 1 << 30)).IsTrue(); + await Assert.That(BitOperations.IsPow2((nint) 0)).IsFalse(); + await Assert.That(BitOperations.IsPow2((nint) 3)).IsFalse(); + await Assert.That(BitOperations.IsPow2((nint) (-2))).IsFalse(); + } + + [Test] + public async Task BitOperations_IsPow2Nuint() + { + await Assert.That(BitOperations.IsPow2((nuint) 1)).IsTrue(); + await Assert.That(BitOperations.IsPow2((nuint) 1 << 30)).IsTrue(); + await Assert.That(BitOperations.IsPow2((nuint) 0)).IsFalse(); + await Assert.That(BitOperations.IsPow2((nuint) 3)).IsFalse(); + } +}