Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions src/libraries/System.Private.CoreLib/src/System/Double.cs
Original file line number Diff line number Diff line change
Expand Up @@ -533,12 +533,28 @@ public static bool IsPow2(double value)
{
ulong bits = BitConverter.DoubleToUInt64Bits(value);

ushort biasedExponent = ExtractBiasedExponentFromBits(bits);;
if ((long)bits <= 0)
{
// Zero and negative values cannot be powers of 2
return false;
}

ushort biasedExponent = ExtractBiasedExponentFromBits(bits);
ulong trailingSignificand = ExtractTrailingSignificandFromBits(bits);

return (value > 0)
&& (biasedExponent != MinBiasedExponent) && (biasedExponent != MaxBiasedExponent)
&& (trailingSignificand == MinTrailingSignificand);
if (biasedExponent == MinBiasedExponent)
{
// Subnormal values have 1 bit set when they're powers of 2
return ulong.PopCount(trailingSignificand) == 1;
}
else if (biasedExponent == MaxBiasedExponent)
{
// NaN and Infinite values cannot be powers of 2
return false;
}

// Normal values have 0 bits set when they're powers of 2
return trailingSignificand == MinTrailingSignificand;
}

/// <inheritdoc cref="IBinaryNumber{TSelf}.Log2(TSelf)" />
Expand Down
22 changes: 19 additions & 3 deletions src/libraries/System.Private.CoreLib/src/System/Half.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,12 +1194,28 @@ public static bool IsPow2(Half value)
{
ushort bits = BitConverter.HalfToUInt16Bits(value);

if ((short)bits <= 0)
{
// Zero and negative values cannot be powers of 2
return false;
}

byte biasedExponent = ExtractBiasedExponentFromBits(bits);
ushort trailingSignificand = ExtractTrailingSignificandFromBits(bits);

return (value > Zero)
&& (biasedExponent != MinBiasedExponent) && (biasedExponent != MaxBiasedExponent)
&& (trailingSignificand == MinTrailingSignificand);
if (biasedExponent == MinBiasedExponent)
{
// Subnormal values have 1 bit set when they're powers of 2
return ushort.PopCount(trailingSignificand) == 1;
}
else if (biasedExponent == MaxBiasedExponent)
{
// NaN and Infinite values cannot be powers of 2
return false;
}

// Normal values have 0 bits set when they're powers of 2
return trailingSignificand == MinTrailingSignificand;
}

/// <inheritdoc cref="IBinaryNumber{TSelf}.Log2(TSelf)" />
Expand Down
22 changes: 19 additions & 3 deletions src/libraries/System.Private.CoreLib/src/System/Single.cs
Original file line number Diff line number Diff line change
Expand Up @@ -529,12 +529,28 @@ public static bool IsPow2(float value)
{
uint bits = BitConverter.SingleToUInt32Bits(value);

if ((int)bits <= 0)
{
// Zero and negative values cannot be powers of 2
return false;
}

byte biasedExponent = ExtractBiasedExponentFromBits(bits);
uint trailingSignificand = ExtractTrailingSignificandFromBits(bits);

return (value > 0)
&& (biasedExponent != MinBiasedExponent) && (biasedExponent != MaxBiasedExponent)
&& (trailingSignificand == MinTrailingSignificand);
if (biasedExponent == MinBiasedExponent)
{
// Subnormal values have 1 bit set when they're powers of 2
return uint.PopCount(trailingSignificand) == 1;
}
else if (biasedExponent == MaxBiasedExponent)
{
// NaN and Infinite values cannot be powers of 2
return false;
}

// Normal values have 0 bits set when they're powers of 2
return trailingSignificand == MinTrailingSignificand;
}

/// <inheritdoc cref="IBinaryNumber{TSelf}.Log2(TSelf)" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ public static void IsPow2Test()
Assert.False(BinaryNumberHelper<NFloat>.IsPow2(NegativeZero));
Assert.False(BinaryNumberHelper<NFloat>.IsPow2(NFloat.NaN));
Assert.False(BinaryNumberHelper<NFloat>.IsPow2(Zero));
Assert.False(BinaryNumberHelper<NFloat>.IsPow2(NFloat.Epsilon));
Assert.True(BinaryNumberHelper<NFloat>.IsPow2(NFloat.Epsilon));
Assert.False(BinaryNumberHelper<NFloat>.IsPow2(MaxSubnormal));
Assert.True(BinaryNumberHelper<NFloat>.IsPow2(MinNormal));
Assert.True(BinaryNumberHelper<NFloat>.IsPow2(One));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public static void IsPow2Test()
Assert.False(BinaryNumberHelper<double>.IsPow2(-0.0));
Assert.False(BinaryNumberHelper<double>.IsPow2(double.NaN));
Assert.False(BinaryNumberHelper<double>.IsPow2(0.0));
Assert.False(BinaryNumberHelper<double>.IsPow2(double.Epsilon));
Assert.True(BinaryNumberHelper<double>.IsPow2(double.Epsilon));
Assert.False(BinaryNumberHelper<double>.IsPow2(MaxSubnormal));
Assert.True(BinaryNumberHelper<double>.IsPow2(MinNormal));
Assert.True(BinaryNumberHelper<double>.IsPow2(1.0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public static void IsPow2Test()
Assert.False(BinaryNumberHelper<Half>.IsPow2(NegativeZero));
Assert.False(BinaryNumberHelper<Half>.IsPow2(Half.NaN));
Assert.False(BinaryNumberHelper<Half>.IsPow2(Zero));
Assert.False(BinaryNumberHelper<Half>.IsPow2(Half.Epsilon));
Assert.True(BinaryNumberHelper<Half>.IsPow2(Half.Epsilon));
Assert.False(BinaryNumberHelper<Half>.IsPow2(MaxSubnormal));
Assert.True(BinaryNumberHelper<Half>.IsPow2(MinNormal));
Assert.True(BinaryNumberHelper<Half>.IsPow2(One));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public static void IsPow2Test()
Assert.False(BinaryNumberHelper<float>.IsPow2(-0.0f));
Assert.False(BinaryNumberHelper<float>.IsPow2(float.NaN));
Assert.False(BinaryNumberHelper<float>.IsPow2(0.0f));
Assert.False(BinaryNumberHelper<float>.IsPow2(float.Epsilon));
Assert.True(BinaryNumberHelper<float>.IsPow2(float.Epsilon));
Assert.False(BinaryNumberHelper<float>.IsPow2(MaxSubnormal));
Assert.True(BinaryNumberHelper<float>.IsPow2(MinNormal));
Assert.True(BinaryNumberHelper<float>.IsPow2(1.0f));
Expand Down