1
0
mirror of https://github.com/chylex/.NET-Community-Toolkit.git synced 2025-08-30 02:53:09 +02:00
Files
CommunityToolkit.Common
CommunityToolkit.Diagnostics
CommunityToolkit.HighPerformance
Attributes
Buffers
Enumerables
Extensions
ArrayExtensions.1D.cs
ArrayExtensions.2D.cs
ArrayExtensions.3D.cs
ArrayPoolBufferWriterExtensions.cs
ArrayPoolExtensions.cs
BoolExtensions.cs
HashCodeExtensions.cs
IBufferWriterExtensions.cs
IMemoryOwnerExtensions.cs
ListExtensions.cs
MemoryExtensions.cs
NullableExtensions.cs
ReadOnlyMemoryExtensions.cs
ReadOnlySpanExtensions.cs
SpanExtensions.cs
SpinLockExtensions.cs
StreamExtensions.cs
StringExtensions.cs
Helpers
Memory
Properties
Streams
Box{T}.cs
CommunityToolkit.HighPerformance.csproj
NullableReadOnlyRef{T}.cs
NullableRef{T}.cs
ReadOnlyRef{T}.cs
Ref{T}.cs
CommunityToolkit.Mvvm
CommunityToolkit.Mvvm.SourceGenerators
build
tests
.editorconfig
.git-blame-ignore-revs
.gitattributes
.gitignore
.runsettings
CODE_OF_CONDUCT.md
Contributing.md
Directory.Build.props
Directory.Build.targets
License.md
README.md
ThirdPartyNotices.txt
azure-pipelines.yml
dotnet Community Toolkit.sln
toolkit.snk
version.json
.NET-Community-Toolkit/CommunityToolkit.HighPerformance/Extensions/BoolExtensions.cs
2021-11-01 23:42:45 +01:00

80 lines
3.5 KiB
C#

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
namespace CommunityToolkit.HighPerformance;
/// <summary>
/// Helpers for working with the <see cref="bool"/> type.
/// </summary>
public static class BoolExtensions
{
/// <summary>
/// Converts the given <see cref="bool"/> value into a <see cref="byte"/>.
/// </summary>
/// <param name="flag">The input value to convert.</param>
/// <returns>1 if <paramref name="flag"/> is <see langword="true"/>, 0 otherwise.</returns>
/// <remarks>This method does not contain branching instructions.</remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe byte ToByte(this bool flag)
{
// Whenever we need to take the address of an argument, we make a local copy first.
// This will be removed by the JIT anyway, but it can help produce better codegen and
// remove unwanted stack spills if the caller is using constant arguments. This is
// because taking the address of an argument can interfere with some of the flow
// analysis executed by the JIT, which can in some cases block constant propagation.
bool copy = flag;
return *(byte*)&copy;
}
/// <summary>
/// Converts the given <see cref="bool"/> value to an <see cref="int"/> mask with
/// all bits representing the value of the input flag (either 0xFFFFFFFF or 0x00000000).
/// </summary>
/// <param name="flag">The input value to convert.</param>
/// <returns>0xFFFFFFFF if <paramref name="flag"/> is <see langword="true"/>, 0x00000000 otherwise.</returns>
/// <remarks>
/// This method does not contain branching instructions, and it is only guaranteed to work with
/// <see cref="bool"/> values being either 0 or 1. Operations producing a <see cref="bool"/> result,
/// such as numerical comparisons, always result in a valid value. If the <see cref="bool"/> value is
/// produced by fields with a custom <see cref="System.Runtime.InteropServices.FieldOffsetAttribute"/>,
/// or by using <see cref="Unsafe.As{T}"/> or other unsafe APIs to directly manipulate the underlying
/// data though, it is responsibility of the caller to ensure the validity of the provided value.
/// </remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe int ToBitwiseMask32(this bool flag)
{
bool copy = flag;
byte rangeFlag = *(byte*)&copy;
int negativeFlag = rangeFlag - 1;
int mask = ~negativeFlag;
return mask;
}
/// <summary>
/// Converts the given <see cref="bool"/> value to a <see cref="long"/> mask with
/// all bits representing the value of the input flag (either all 1s or 0s).
/// </summary>
/// <param name="flag">The input value to convert.</param>
/// <returns>All 1s if <paramref name="flag"/> is <see langword="true"/>, all 0s otherwise.</returns>
/// <remarks>This method does not contain branching instructions. See additional note in <see cref="ToBitwiseMask32"/>.</remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe long ToBitwiseMask64(this bool flag)
{
bool copy = flag;
byte rangeFlag = *(byte*)&copy;
long negativeFlag = (long)rangeFlag - 1;
long mask = ~negativeFlag;
return mask;
}
}