Skip to content

Commit

Permalink
Ensure that CreateChecked, CreateSaturating, and CreateTruncating are…
Browse files Browse the repository at this point in the history
… publicly exposed (#71493)

* Ensure that CreateChecked, CreateSaturating, and CreateTruncating are publicly exposed

* Fixing the constraint on the private TryConvertFrom helpers
  • Loading branch information
tannergooding committed Jul 7, 2022
1 parent 29fcb7f commit 162cca2
Show file tree
Hide file tree
Showing 22 changed files with 1,340 additions and 40 deletions.
75 changes: 72 additions & 3 deletions src/libraries/System.Private.CoreLib/src/System/Byte.cs
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,63 @@ bool IBinaryInteger<byte>.TryWriteLittleEndian(Span<byte> destination, out int b
/// <inheritdoc cref="INumberBase{TSelf}.Abs(TSelf)" />
static byte INumberBase<byte>.Abs(byte value) => value;

/// <inheritdoc cref="INumberBase{TSelf}.CreateChecked{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte CreateChecked<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
byte result;

if (typeof(TOther) == typeof(byte))
{
result = (byte)(object)value;
}
else if (!TryConvertFromChecked(value, out result) && !TOther.TryConvertToChecked(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}

return result;
}

/// <inheritdoc cref="INumberBase{TSelf}.CreateSaturating{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte CreateSaturating<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
byte result;

if (typeof(TOther) == typeof(byte))
{
result = (byte)(object)value;
}
else if (!TryConvertFromSaturating(value, out result) && !TOther.TryConvertToSaturating(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}

return result;
}

/// <inheritdoc cref="INumberBase{TSelf}.CreateTruncating{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte CreateTruncating<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
byte result;

if (typeof(TOther) == typeof(byte))
{
result = (byte)(object)value;
}
else if (!TryConvertFromTruncating(value, out result) && !TOther.TryConvertToTruncating(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}

return result;
}

/// <inheritdoc cref="INumberBase{TSelf}.IsCanonical(TSelf)" />
static bool INumberBase<byte>.IsCanonical(byte value) => true;

Expand Down Expand Up @@ -596,7 +653,11 @@ bool IBinaryInteger<byte>.TryWriteLittleEndian(Span<byte> destination, out int b

/// <inheritdoc cref="INumberBase{TSelf}.TryConvertFromChecked{TOther}(TOther, out TSelf)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool INumberBase<byte>.TryConvertFromChecked<TOther>(TOther value, out byte result)
static bool INumberBase<byte>.TryConvertFromChecked<TOther>(TOther value, out byte result) => TryConvertFromChecked(value, out result);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryConvertFromChecked<TOther>(TOther value, out byte result)
where TOther : INumberBase<TOther>
{
// In order to reduce overall code duplication and improve the inlinabilty of these
// methods for the corelib types we have `ConvertFrom` handle the same sign and
Expand Down Expand Up @@ -658,7 +719,11 @@ static bool INumberBase<byte>.TryConvertFromChecked<TOther>(TOther value, out by

/// <inheritdoc cref="INumberBase{TSelf}.TryConvertFromSaturating{TOther}(TOther, out TSelf)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool INumberBase<byte>.TryConvertFromSaturating<TOther>(TOther value, out byte result)
static bool INumberBase<byte>.TryConvertFromSaturating<TOther>(TOther value, out byte result) => TryConvertFromSaturating(value, out result);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryConvertFromSaturating<TOther>(TOther value, out byte result)
where TOther : INumberBase<TOther>
{
// In order to reduce overall code duplication and improve the inlinabilty of these
// methods for the corelib types we have `ConvertFrom` handle the same sign and
Expand Down Expand Up @@ -721,7 +786,11 @@ static bool INumberBase<byte>.TryConvertFromSaturating<TOther>(TOther value, out

/// <inheritdoc cref="INumberBase{TSelf}.TryConvertFromTruncating{TOther}(TOther, out TSelf)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool INumberBase<byte>.TryConvertFromTruncating<TOther>(TOther value, out byte result)
static bool INumberBase<byte>.TryConvertFromTruncating<TOther>(TOther value, out byte result) => TryConvertFromTruncating(value, out result);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryConvertFromTruncating<TOther>(TOther value, out byte result)
where TOther : INumberBase<TOther>
{
// In order to reduce overall code duplication and improve the inlinabilty of these
// methods for the corelib types we have `ConvertFrom` handle the same sign and
Expand Down
63 changes: 62 additions & 1 deletion src/libraries/System.Private.CoreLib/src/System/Decimal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,63 @@ public static decimal Abs(decimal value)
return new decimal(in value, value._flags & ~SignMask);
}

/// <inheritdoc cref="INumberBase{TSelf}.CreateChecked{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static decimal CreateChecked<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
decimal result;

if (typeof(TOther) == typeof(decimal))
{
result = (decimal)(object)value;
}
else if (!TryConvertFromChecked(value, out result) && !TOther.TryConvertToChecked(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}

return result;
}

/// <inheritdoc cref="INumberBase{TSelf}.CreateSaturating{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static decimal CreateSaturating<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
decimal result;

if (typeof(TOther) == typeof(decimal))
{
result = (decimal)(object)value;
}
else if (!TryConvertFrom(value, out result) && !TOther.TryConvertToSaturating(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}

return result;
}

/// <inheritdoc cref="INumberBase{TSelf}.CreateTruncating{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static decimal CreateTruncating<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
decimal result;

if (typeof(TOther) == typeof(decimal))
{
result = (decimal)(object)value;
}
else if (!TryConvertFrom(value, out result) && !TOther.TryConvertToTruncating(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}

return result;
}

/// <inheritdoc cref="INumberBase{TSelf}.IsCanonical(TSelf)" />
public static bool IsCanonical(decimal value)
{
Expand Down Expand Up @@ -1434,7 +1491,11 @@ public static decimal MinMagnitude(decimal x, decimal y)

/// <inheritdoc cref="INumberBase{TSelf}.TryConvertFromChecked{TOther}(TOther, out TSelf)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool INumberBase<decimal>.TryConvertFromChecked<TOther>(TOther value, out decimal result)
static bool INumberBase<decimal>.TryConvertFromChecked<TOther>(TOther value, out decimal result) => TryConvertFromChecked(value, out result);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryConvertFromChecked<TOther>(TOther value, out decimal result)
where TOther : INumberBase<TOther>
{
// In order to reduce overall code duplication and improve the inlinabilty of these
// methods for the corelib types we have `ConvertFrom` handle the same sign and
Expand Down
57 changes: 57 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Double.cs
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,63 @@ public static double MinNumber(double x, double y)
/// <inheritdoc cref="INumberBase{TSelf}.Abs(TSelf)" />
public static double Abs(double value) => Math.Abs(value);

/// <inheritdoc cref="INumberBase{TSelf}.CreateChecked{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double CreateChecked<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
double result;

if (typeof(TOther) == typeof(double))
{
result = (double)(object)value;
}
else if (!TryConvertFrom(value, out result) && !TOther.TryConvertToChecked(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}

return result;
}

/// <inheritdoc cref="INumberBase{TSelf}.CreateSaturating{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double CreateSaturating<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
double result;

if (typeof(TOther) == typeof(double))
{
result = (double)(object)value;
}
else if (!TryConvertFrom(value, out result) && !TOther.TryConvertToSaturating(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}

return result;
}

/// <inheritdoc cref="INumberBase{TSelf}.CreateTruncating{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double CreateTruncating<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
double result;

if (typeof(TOther) == typeof(double))
{
result = (double)(object)value;
}
else if (!TryConvertFrom(value, out result) && !TOther.TryConvertToTruncating(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}

return result;
}

/// <inheritdoc cref="INumberBase{TSelf}.IsCanonical(TSelf)" />
static bool INumberBase<double>.IsCanonical(double value) => true;

Expand Down
57 changes: 57 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Half.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,63 @@ public static Half MinNumber(Half x, Half y)
/// <inheritdoc cref="INumberBase{TSelf}.Abs(TSelf)" />
public static Half Abs(Half value) => (Half)MathF.Abs((float)value);

/// <inheritdoc cref="INumberBase{TSelf}.CreateChecked{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Half CreateChecked<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
Half result;

if (typeof(TOther) == typeof(Half))
{
result = (Half)(object)value;
}
else if (!TryConvertFrom(value, out result) && !TOther.TryConvertToChecked(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}

return result;
}

/// <inheritdoc cref="INumberBase{TSelf}.CreateSaturating{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Half CreateSaturating<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
Half result;

if (typeof(TOther) == typeof(Half))
{
result = (Half)(object)value;
}
else if (!TryConvertFrom(value, out result) && !TOther.TryConvertToSaturating(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}

return result;
}

/// <inheritdoc cref="INumberBase{TSelf}.CreateTruncating{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Half CreateTruncating<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
Half result;

if (typeof(TOther) == typeof(Half))
{
result = (Half)(object)value;
}
else if (!TryConvertFrom(value, out result) && !TOther.TryConvertToTruncating(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}

return result;
}

/// <inheritdoc cref="INumberBase{TSelf}.IsCanonical(TSelf)" />
static bool INumberBase<Half>.IsCanonical(Half value) => true;

Expand Down
Loading

0 comments on commit 162cca2

Please sign in to comment.