Files
2025-10-17 02:40:51 +02:00

90 lines
2.7 KiB
C#

using System.Numerics;
using System.Runtime.CompilerServices;
namespace PerfectNumbers.Core.Gpu;
public readonly struct ReadOnlyGpuUInt128 : IEquatable<ReadOnlyGpuUInt128>
{
public readonly ulong High;
public readonly ulong Low;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlyGpuUInt128(ulong high, ulong low)
{
High = high;
Low = low;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlyGpuUInt128(ulong low)
: this(0UL, low)
{
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlyGpuUInt128(UInt128 value)
{
High = (ulong)(value >> 64);
Low = (ulong)value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlyGpuUInt128(GpuUInt128 value)
{
High = value.High;
Low = value.Low;
}
public bool IsZero
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => High == 0UL && Low == 0UL;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetBitLength()
{
if (High != 0UL)
{
return 64 + (64 - BitOperations.LeadingZeroCount(High));
}
if (Low == 0UL)
{
return 0;
}
return 64 - BitOperations.LeadingZeroCount(Low);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public GpuUInt128 ToMutable() => new(High, Low);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(ReadOnlyGpuUInt128 other) => High == other.High && Low == other.Low;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object? obj) => obj is ReadOnlyGpuUInt128 other && Equals(other);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() => HashCode.Combine(High, Low);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ReadOnlyGpuUInt128(ulong value) => new(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ReadOnlyGpuUInt128(UInt128 value) => new(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ReadOnlyGpuUInt128(GpuUInt128 value) => new(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator UInt128(ReadOnlyGpuUInt128 value) => ((UInt128)value.High << 64) | value.Low;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlyGpuUInt128 WithHigh(ulong high) => new(high, Low);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlyGpuUInt128 WithLow(ulong low) => new(High, low);
}