mirror of
https://github.com/chylex/.NET-Community-Toolkit.git
synced 2024-11-24 07:42:45 +01:00
76 lines
3.5 KiB
C#
76 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.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>
|
|
[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*)©
|
|
}
|
|
|
|
/// <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>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static unsafe int ToBitwiseMask32(this bool flag)
|
|
{
|
|
bool copy = flag;
|
|
byte rangeFlag = *(byte*)©
|
|
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>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static unsafe long ToBitwiseMask64(this bool flag)
|
|
{
|
|
bool copy = flag;
|
|
byte rangeFlag = *(byte*)©
|
|
long negativeFlag = (long)rangeFlag - 1;
|
|
long mask = ~negativeFlag;
|
|
|
|
return mask;
|
|
}
|
|
}
|