|
|
|
@ -583,260 +583,6 @@ internal sealed class JxlFastLosslessEncoder |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// SIMD Mask32
|
|
|
|
/// </summary>
|
|
|
|
private struct Mask32 |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// Actual mask.
|
|
|
|
/// </summary>
|
|
|
|
public ushort Mask; |
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
|
public readonly uint CountPrefix() => CtzNonZero(~(uint)this.Mask); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Wrapper over a 32-bit integer vector.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="vector">Underlying vector.</param>
|
|
|
|
private struct SimdVec32(Vector<uint> vector) |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// The actual vector for this simd vector.
|
|
|
|
/// </summary>
|
|
|
|
public Vector<uint> Vec = vector; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Adds both vectors.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First vector</param>
|
|
|
|
/// <param name="b">Second vector</param>
|
|
|
|
/// <returns>a + b</returns>
|
|
|
|
public static SimdVec32 operator +(SimdVec32 a, SimdVec32 b) => new(a.Vec + b.Vec); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Subtracts both vectors.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First vector</param>
|
|
|
|
/// <param name="b">Second vector</param>
|
|
|
|
/// <returns>a - b</returns>
|
|
|
|
public static SimdVec32 operator -(SimdVec32 a, SimdVec32 b) => new(a.Vec - b.Vec); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// XORs both vectors.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First vector</param>
|
|
|
|
/// <param name="b">Second vector</param>
|
|
|
|
/// <returns>a ^ b</returns>
|
|
|
|
public static SimdVec32 operator ^(SimdVec32 a, SimdVec32 b) => new(a.Vec ^ b.Vec); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Sets bits to all 1 if vector items are equal, otherwise to all 0.
|
|
|
|
/// For example, if vector a is {5, 2, 4, 1} and vector b is {7, 3, 4, 5}
|
|
|
|
/// the result is {0, 0, 0xFFFFFFFF, 0}.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First vector</param>
|
|
|
|
/// <param name="b">Second vector</param>
|
|
|
|
/// <returns>a == b</returns>
|
|
|
|
public static SimdVec32 operator ==(SimdVec32 a, SimdVec32 b) => new(Vector.Equals(a.Vec, b.Vec)); |
|
|
|
|
|
|
|
// We don't use this. It's to remove an error where == requires !=.
|
|
|
|
public static SimdVec32 operator !=(SimdVec32 a, SimdVec32 b) => new(Vector.Equals(a.Vec, b.Vec)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Sets bits to all 1 if vector items are larger, otherwise to all 0.
|
|
|
|
/// For example, if vector a is {5, 2, 4, 1} and vector b is {3, 3, 4, 5}
|
|
|
|
/// the result is {0xFFFFFFFF, 0, 0, 0}.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First vector</param>
|
|
|
|
/// <param name="b">Second vector</param>
|
|
|
|
/// <returns>a > b</returns>
|
|
|
|
public static SimdVec32 operator >(SimdVec32 a, SimdVec32 b) => new(Vector.GreaterThan(a.Vec, b.Vec)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Sets bits to all 1 if vector items are lower, otherwise to all 0.
|
|
|
|
/// For example, if vector a is {5, 2, 4, 1} and vector b is {3, 3, 4, 5}
|
|
|
|
/// the result is {0, 0xFFFFFFFF, 0, 0xFFFFFFFF}.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First vector</param>
|
|
|
|
/// <param name="b">Second vector</param>
|
|
|
|
/// <returns>a < b</returns>
|
|
|
|
public static SimdVec32 operator <(SimdVec32 a, SimdVec32 b) => new(Vector.LessThan(a.Vec, b.Vec)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Converts this vector to a mask.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>
|
|
|
|
/// Mask where bits are 1 if the item
|
|
|
|
/// at the index is set to all 1, otherwise 0.
|
|
|
|
/// </returns>
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
|
public readonly Mask32 ToMask() |
|
|
|
{ |
|
|
|
int mask = 0; |
|
|
|
|
|
|
|
for (int i = 0; i < 16 && i < Vector<int>.Count; i++) |
|
|
|
{ |
|
|
|
if (this.Vec[i] == uint.MaxValue) |
|
|
|
{ |
|
|
|
mask |= 1 << i; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return new() { Mask = (ushort)mask }; |
|
|
|
} |
|
|
|
|
|
|
|
public static SimdVec32 Load(Span<uint> data) => new(new Vector<uint>(data)); |
|
|
|
|
|
|
|
public static SimdVec32 Value(uint value) => new(new Vector<uint>(value)); |
|
|
|
|
|
|
|
public readonly SimdVec32 ValueToToken() => new(new Vector<uint>(32u) - GetLzcnt(this.Vec)); |
|
|
|
|
|
|
|
public readonly SimdVec32 SaturateSubtract(SimdVec32 toSubtract) => new(Vector.Max(this.Vec, toSubtract.Vec) - toSubtract.Vec); |
|
|
|
|
|
|
|
public readonly SimdVec32 Pow2() => new(Vector.ShiftLeft(Vector<uint>.One, unchecked((int)this.Vec[0]))); |
|
|
|
|
|
|
|
public readonly void Store(Span<uint> data) => this.Vec.CopyTo(data); |
|
|
|
|
|
|
|
// We don't use this.
|
|
|
|
public override readonly bool Equals(object? obj) => false; |
|
|
|
|
|
|
|
// We don't use this.
|
|
|
|
public override readonly int GetHashCode() => this.Vec.GetHashCode(); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// SIMD Mask16
|
|
|
|
/// </summary>
|
|
|
|
private struct Mask16 |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// Actual mask.
|
|
|
|
/// </summary>
|
|
|
|
public uint Mask; |
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
|
public readonly uint CountPrefix() => CtzNonZero(~this.Mask); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Wrapper over a 16-bit integer vector.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="vector">Underlying vector.</param>
|
|
|
|
private struct SimdVec16(Vector<ushort> vector) |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// The actual vector for this simd vector.
|
|
|
|
/// </summary>
|
|
|
|
public Vector<ushort> Vec = vector; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Adds both vectors.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First vector</param>
|
|
|
|
/// <param name="b">Second vector</param>
|
|
|
|
/// <returns>a + b</returns>
|
|
|
|
public static SimdVec16 operator +(SimdVec16 a, SimdVec16 b) => new(a.Vec + b.Vec); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Subtracts both vectors.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First vector</param>
|
|
|
|
/// <param name="b">Second vector</param>
|
|
|
|
/// <returns>a - b</returns>
|
|
|
|
public static SimdVec16 operator -(SimdVec16 a, SimdVec16 b) => new(a.Vec - b.Vec); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// XORs both vectors.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First vector</param>
|
|
|
|
/// <param name="b">Second vector</param>
|
|
|
|
/// <returns>a ^ b</returns>
|
|
|
|
public static SimdVec16 operator ^(SimdVec16 a, SimdVec16 b) => new(a.Vec ^ b.Vec); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Sets bits to all 1 if vector items are equal, otherwise to all 0.
|
|
|
|
/// For example, if vector a is {5, 2, 4, 1} and vector b is {7, 3, 4, 5}
|
|
|
|
/// the result is {0, 0, 0xFFFF, 0}.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First vector</param>
|
|
|
|
/// <param name="b">Second vector</param>
|
|
|
|
/// <returns>a == b</returns>
|
|
|
|
public static SimdVec16 operator ==(SimdVec16 a, SimdVec16 b) => new(Vector.Equals(a.Vec, b.Vec)); |
|
|
|
|
|
|
|
// We don't use this. It's to remove an error where == requires !=.
|
|
|
|
public static SimdVec16 operator !=(SimdVec16 a, SimdVec16 b) => new(Vector.Equals(a.Vec, b.Vec)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Sets bits to all 1 if vector items are larger, otherwise to all 0.
|
|
|
|
/// For example, if vector a is {5, 2, 4, 1} and vector b is {3, 3, 4, 5}
|
|
|
|
/// the result is {0xFFFF, 0, 0, 0}.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First vector</param>
|
|
|
|
/// <param name="b">Second vector</param>
|
|
|
|
/// <returns>a > b</returns>
|
|
|
|
public static SimdVec16 operator >(SimdVec16 a, SimdVec16 b) => new(Vector.GreaterThan(a.Vec, b.Vec)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Sets bits to all 1 if vector items are lower, otherwise to all 0.
|
|
|
|
/// For example, if vector a is {5, 2, 4, 1} and vector b is {3, 3, 4, 5}
|
|
|
|
/// the result is {0, 0xFFFF, 0, 0xFFFF}.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First vector</param>
|
|
|
|
/// <param name="b">Second vector</param>
|
|
|
|
/// <returns>a < b</returns>
|
|
|
|
public static SimdVec16 operator <(SimdVec16 a, SimdVec16 b) => new(Vector.LessThan(a.Vec, b.Vec)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Converts this vector to a mask.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>
|
|
|
|
/// Mask where bits are 1 if the item
|
|
|
|
/// at the index is set to all 1, otherwise 0.
|
|
|
|
/// </returns>
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
|
public readonly Mask16 ToMask() |
|
|
|
{ |
|
|
|
uint mask = 0; |
|
|
|
|
|
|
|
for (int i = 0; i < 32 && i < Vector<ushort>.Count; i++) |
|
|
|
{ |
|
|
|
if (this.Vec[i] == ushort.MaxValue) |
|
|
|
{ |
|
|
|
mask |= 1u << i; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return new() { Mask = mask }; |
|
|
|
} |
|
|
|
|
|
|
|
public static SimdVec16 FromTwo32(SimdVec32 lo, SimdVec32 hi) |
|
|
|
{ |
|
|
|
Vector<ushort> narrow = Vector.Narrow(lo.Vec, hi.Vec); |
|
|
|
return new(narrow); |
|
|
|
} |
|
|
|
|
|
|
|
public static SimdVec16 Load(Span<ushort> data) => new(new Vector<ushort>(data)); |
|
|
|
|
|
|
|
public static SimdVec16 Value(ushort value) => new(new Vector<ushort>(value)); |
|
|
|
|
|
|
|
public readonly SimdVec16 ValueToToken() => new(new Vector<ushort>(16) - GetLzcnt(this.Vec)); |
|
|
|
|
|
|
|
public readonly SimdVec16 SaturateSubtract(SimdVec16 toSubtract) => new(Vector.Max(this.Vec, toSubtract.Vec) - toSubtract.Vec); |
|
|
|
|
|
|
|
public readonly SimdVec16 Pow2() => new(Vector.ShiftLeft(Vector<ushort>.One, unchecked(this.Vec[0]))); |
|
|
|
|
|
|
|
public readonly void Store(Span<ushort> data) => this.Vec.CopyTo(data); |
|
|
|
|
|
|
|
// We don't use this.
|
|
|
|
public override readonly bool Equals(object? obj) => false; |
|
|
|
|
|
|
|
// We don't use this.
|
|
|
|
public override readonly int GetHashCode() => this.Vec.GetHashCode(); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Pair of two vectors.
|
|
|
|
/// </summary>
|
|
|
|
|