//
// Copyright (c) 2019-2021 Ryujinx
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see .
//
using System;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Utils
{
///
/// A simple bit array implementation backed by a .
///
public class BitArray
{
///
/// The backing storage of the .
///
private Memory _storage;
///
/// Create a new from .
///
/// The backing storage of the .
public BitArray(Memory storage)
{
_storage = storage;
}
///
/// Get the byte position of a given bit index.
///
/// A bit index.
/// The byte position of a given bit index.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int ToPosition(int index) => index / 8;
///
/// Get the bit position of a given bit index inside a byte.
///
/// A bit index.
/// The bit position of a given bit index inside a byte.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int ToBitPosition(int index) => index % 8;
///
/// Test if the bit at the given index is set.
///
/// A bit index.
/// Return true if the bit at the given index is set
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Test(int index)
{
ulong mask = 1ul << ToBitPosition(index);
return (_storage.Span[ToPosition(index)] & mask) == mask;
}
///
/// Set the bit at the given index.
///
/// A bit index.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Set(int index)
{
Set(index, true);
}
///
/// Reset the bit at the given index.
///
/// A bit index.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset(int index)
{
Set(index, false);
}
///
/// Set a bit value at the given index.
///
/// A bit index.
/// The new bit value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Set(int index, bool value)
{
byte mask = (byte)(1 << ToBitPosition(index));
if (value)
{
_storage.Span[ToPosition(index)] |= mask;
}
else
{
_storage.Span[ToPosition(index)] &= (byte)~mask;
}
}
///
/// Reset all bits in the storage.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset()
{
_storage.Span.Fill(0);
}
}
}