Skip to content

Implement Vector.Ceiling / Vector.Floor #31993

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Mar 16, 2020
Next Next commit
Add Ceil/Floor to S.P.CoreLib and expose publicly
  • Loading branch information
Gnbrkm41 committed Mar 16, 2020
commit 138830835bd1ac0c38a77c20b61e15dbe870f2dd
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ public static partial class Vector
[System.CLSCompliantAttribute(false)]
public static void Widen(System.Numerics.Vector<System.UInt32> source, out System.Numerics.Vector<System.UInt64> dest1, out System.Numerics.Vector<System.UInt64> dest2) { throw null; }
public static System.Numerics.Vector<T> Xor<T>(System.Numerics.Vector<T> left, System.Numerics.Vector<T> right) where T : struct { throw null; }
public static System.Numerics.Vector<System.Single> Ceiling(System.Numerics.Vector<System.Single> value) { throw null; }
public static System.Numerics.Vector<System.Double> Ceiling(System.Numerics.Vector<System.Double> value) { throw null; }
public static System.Numerics.Vector<System.Single> Floor(System.Numerics.Vector<System.Single> value) { throw null; }
public static System.Numerics.Vector<System.Double> Floor(System.Numerics.Vector<System.Double> value) { throw null; }
}
public partial struct Vector2 : System.IEquatable<System.Numerics.Vector2>, System.IFormattable
{
Expand Down
100 changes: 100 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3456,6 +3456,106 @@ internal static unsafe Vector<T> SquareRoot(Vector<T> value)
}
}
}

internal static unsafe Vector<T> Ceiling(Vector<T> value)
{
if (Vector.IsHardwareAccelerated)
{
if (typeof(T) == typeof(float))
{
float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
dataPtr[g] = MathF.Ceiling((float)(object)value[g]);
}
return new Vector<T>(dataPtr);
}
else if (typeof(T) == typeof(double))
{
double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
dataPtr[g] = Math.Ceiling((double)(object)value[g]);
}
return new Vector<T>(dataPtr);
}
else
{
throw new NotSupportedException(SR.Arg_TypeNotSupported);
}
}
else
{
if (typeof(T) == typeof(float))
{
value.register.single_0 = MathF.Ceiling(value.register.single_0);
value.register.single_1 = MathF.Ceiling(value.register.single_1);
value.register.single_2 = MathF.Ceiling(value.register.single_2);
value.register.single_3 = MathF.Ceiling(value.register.single_3);
return value;
}
else if (typeof(T) == typeof(double))
{
value.register.double_0 = Math.Ceiling(value.register.double_0);
value.register.double_1 = Math.Ceiling(value.register.double_1);
return value;
}
else
{
throw new NotSupportedException(SR.Arg_TypeNotSupported);
}
}
}

internal static unsafe Vector<T> Floor(Vector<T> value)
{
if (Vector.IsHardwareAccelerated)
{
if (typeof(T) == typeof(float))
{
float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
dataPtr[g] = MathF.Floor((float)(object)value[g]);
}
return new Vector<T>(dataPtr);
}
else if (typeof(T) == typeof(double))
{
double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
dataPtr[g] = Math.Floor((double)(object)value[g]);
}
return new Vector<T>(dataPtr);
}
else
{
throw new NotSupportedException(SR.Arg_TypeNotSupported);
}
}
else
{
if (typeof(T) == typeof(float))
{
value.register.single_0 = MathF.Floor(value.register.single_0);
value.register.single_1 = MathF.Floor(value.register.single_1);
value.register.single_2 = MathF.Floor(value.register.single_2);
value.register.single_3 = MathF.Floor(value.register.single_3);
return value;
}
else if (typeof(T) == typeof(double))
{
value.register.double_0 = Math.Floor(value.register.double_0);
value.register.double_1 = Math.Floor(value.register.double_1);
return value;
}
else
{
throw new NotSupportedException(SR.Arg_TypeNotSupported);
}
}
}
#endregion Internal Math Methods

#region Helper Methods
Expand Down
120 changes: 120 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.tt
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,126 @@ namespace System.Numerics
}
}
}

internal static unsafe Vector<T> Ceiling(Vector<T> value)
{
if (Vector.IsHardwareAccelerated)
{
if (typeof(T) == typeof(float))
{
float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
dataPtr[g] = MathF.Ceiling((float)(object)value[g]);
}
return new Vector<T>(dataPtr);
}
else if (typeof(T) == typeof(double))
{
double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
dataPtr[g] = Math.Ceiling((double)(object)value[g]);
}
return new Vector<T>(dataPtr);
}
else
{
throw new NotSupportedException(SR.Arg_TypeNotSupported);
}
}
else
{
if (typeof(T) == typeof(float))
{
<#
for (int g = 0; g < GetNumFields(typeof(float), totalSize); g++)
{
#>
value.<#=GetRegisterFieldName(typeof(float), g)#> = MathF.Ceiling(value.<#=GetRegisterFieldName(typeof(float), g)#>);
<#
}
#>
return value;
}
else if (typeof(T) == typeof(double))
{
<#
for (int g = 0; g < GetNumFields(typeof(double), totalSize); g++)
{
#>
value.<#=GetRegisterFieldName(typeof(double), g)#> = Math.Ceiling(value.<#=GetRegisterFieldName(typeof(double), g)#>);
<#
}
#>
return value;
}
else
{
throw new NotSupportedException(SR.Arg_TypeNotSupported);
}
}
}

internal static unsafe Vector<T> Floor(Vector<T> value)
{
if (Vector.IsHardwareAccelerated)
{
if (typeof(T) == typeof(float))
{
float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
dataPtr[g] = MathF.Floor((float)(object)value[g]);
}
return new Vector<T>(dataPtr);
}
else if (typeof(T) == typeof(double))
{
double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
dataPtr[g] = Math.Floor((double)(object)value[g]);
}
return new Vector<T>(dataPtr);
}
else
{
throw new NotSupportedException(SR.Arg_TypeNotSupported);
}
}
else
{
if (typeof(T) == typeof(float))
{
<#
for (int g = 0; g < GetNumFields(typeof(float), totalSize); g++)
{
#>
value.<#=GetRegisterFieldName(typeof(float), g)#> = MathF.Floor(value.<#=GetRegisterFieldName(typeof(float), g)#>);
<#
}
#>
return value;
}
else if (typeof(T) == typeof(double))
{
<#
for (int g = 0; g < GetNumFields(typeof(double), totalSize); g++)
{
#>
value.<#=GetRegisterFieldName(typeof(double), g)#> = Math.Floor(value.<#=GetRegisterFieldName(typeof(double), g)#>);
<#
}
#>
return value;
}
else
{
throw new NotSupportedException(SR.Arg_TypeNotSupported);
}
}
}
#endregion Internal Math Methods

#region Helper Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,70 @@ public static Vector<T> SquareRoot<T>(Vector<T> value) where T : struct
{
return Vector<T>.SquareRoot(value);
}

/// <summary>
/// Returns a new vector whose elements are the smallest integral values that are greater than or equal to the given vector's elements.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>
/// The vector whose elements are the smallest integral values that are greater than or equal to the given vector's elements.
/// If a value is equal to <see cref="float.NaN"/>, <see cref="float.NegativeInfinity"/> or <see cref="float.PositiveInfinity"/>, that value is returned.
/// Note that this method returns a <see cref="float"/> instead of an integral type.
/// </returns>
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector<float> Ceiling(Vector<float> value)
{
return Vector<float>.Ceiling(value);
}

/// <summary>
/// Returns a new vector whose elements are the smallest integral values that are greater than or equal to the given vector's elements.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>
/// The vector whose elements are the smallest integral values that are greater than or equal to the given vector's elements.
/// If a value is equal to <see cref="double.NaN"/>, <see cref="double.NegativeInfinity"/> or <see cref="double.PositiveInfinity"/>, that value is returned.
/// Note that this method returns a <see cref="double"/> instead of an integral type.
/// </returns>
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector<double> Ceiling(Vector<double> value)
{
return Vector<double>.Ceiling(value);
}

/// <summary>
/// Returns a new vector whose elements are the largest integral values that are less than or equal to the given vector's elements.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>
/// The vector whose elements are the largest integral values that are less than or equal to the given vector's elements.
/// If a value is equal to <see cref="float.NaN"/>, <see cref="float.NegativeInfinity"/> or <see cref="float.PositiveInfinity"/>, that value is returned.
/// Note that this method returns a <see cref="float"/> instead of an integral type.
/// </returns>
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector<float> Floor(Vector<float> value)
{
return Vector<float>.Floor(value);
}

/// <summary>
/// Returns a new vector whose elements are the largest integral values that are less than or equal to the given vector's elements.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>
/// The vector whose elements are the largest integral values that are less than or equal to the given vector's elements.
/// If a value is equal to <see cref="double.NaN"/>, <see cref="double.NegativeInfinity"/> or <see cref="double.PositiveInfinity"/>, that value is returned.
/// Note that this method returns a <see cref="double"/> instead of an integral type.
/// </returns>
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector<double> Floor(Vector<double> value)
{
return Vector<double>.Floor(value);
}
#endregion Vector Math Methods

#region Named Arithmetic Operators
Expand Down