Skip to content

Commit

Permalink
Add managed implementation of Math.ILogB and MathF.ILogB (#56236)
Browse files Browse the repository at this point in the history
* Added managed implementations for ILogB, removed extern bindings

* Fix bug with managed MathF implementation, removing ILog2 implementation in ecallist and vm

* Add citations to musl implementation.

* Remove whitespace

* Remove Mono bindings

* Add more test cases from musl test library

* Remove native ILogB logic from Mono

* Update citations to official MUSL source
  • Loading branch information
alexcovington committed Oct 19, 2021
1 parent f518b2e commit 838fed9
Show file tree
Hide file tree
Showing 19 changed files with 92 additions and 92 deletions.
4 changes: 0 additions & 4 deletions src/coreclr/System.Private.CoreLib/src/System/Math.CoreCLR.cs
Expand Up @@ -80,10 +80,6 @@ public static partial class Math
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern double FusedMultiplyAdd(double x, double y, double z);

[Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern int ILogB(double x);

[Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern double Log(double d);
Expand Down
Expand Up @@ -69,10 +69,6 @@ public static partial class MathF
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern float FusedMultiplyAdd(float x, float y, float z);

[Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern int ILogB(float x);

[Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern float Log(float x);
Expand Down
9 changes: 0 additions & 9 deletions src/coreclr/classlibnative/float/floatdouble.cpp
Expand Up @@ -208,15 +208,6 @@ FCIMPL3_VVV(double, COMDouble::FusedMultiplyAdd, double x, double y, double z)
return fma(x, y, z);
FCIMPLEND

/*=====================================Ilog2====================================
**
==============================================================================*/
FCIMPL1_V(int, COMDouble::ILogB, double x)
FCALL_CONTRACT;

return ilogb(x);
FCIMPLEND

/*=====================================Log======================================
**
==============================================================================*/
Expand Down
9 changes: 0 additions & 9 deletions src/coreclr/classlibnative/float/floatsingle.cpp
Expand Up @@ -195,15 +195,6 @@ FCIMPL3_VVV(float, COMSingle::FusedMultiplyAdd, float x, float y, float z)
return fmaf(x, y, z);
FCIMPLEND

/*=====================================Ilog2====================================
**
==============================================================================*/
FCIMPL1_V(int, COMSingle::ILogB, float x)
FCALL_CONTRACT;

return ilogbf(x);
FCIMPLEND

/*=====================================Log======================================
**
==============================================================================*/
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/classlibnative/inc/floatdouble.h
Expand Up @@ -25,7 +25,6 @@ class COMDouble {
FCDECL1_V(static double, Floor, double x);
FCDECL2_VV(static double, FMod, double x, double y);
FCDECL3_VVV(static double, FusedMultiplyAdd, double x, double y, double z);
FCDECL1_V(static int, ILogB, double x);
FCDECL1_V(static double, Log, double x);
FCDECL1_V(static double, Log2, double x);
FCDECL1_V(static double, Log10, double x);
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/classlibnative/inc/floatsingle.h
Expand Up @@ -25,7 +25,6 @@ class COMSingle {
FCDECL1_V(static float, Floor, float x);
FCDECL2_VV(static float, FMod, float x, float y);
FCDECL3_VVV(static float, FusedMultiplyAdd, float x, float y, float z);
FCDECL1_V(static int, ILogB, float x);
FCDECL1_V(static float, Log, float x);
FCDECL1_V(static float, Log2, float x);
FCDECL1_V(static float, Log10, float x);
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/vm/ecalllist.h
Expand Up @@ -512,7 +512,6 @@ FCFuncStart(gMathFuncs)
FCFuncElement("Floor", COMDouble::Floor)
FCFuncElement("FMod", COMDouble::FMod)
FCFuncElement("FusedMultiplyAdd", COMDouble::FusedMultiplyAdd)
FCFuncElement("ILogB", COMDouble::ILogB)
FCFuncElement("Log", COMDouble::Log)
FCFuncElement("Log2", COMDouble::Log2)
FCFuncElement("Log10", COMDouble::Log10)
Expand Down Expand Up @@ -542,7 +541,6 @@ FCFuncStart(gMathFFuncs)
FCFuncElement("Floor", COMSingle::Floor)
FCFuncElement("FMod", COMSingle::FMod)
FCFuncElement("FusedMultiplyAdd", COMSingle::FusedMultiplyAdd)
FCFuncElement("ILogB", COMSingle::ILogB)
FCFuncElement("Log", COMSingle::Log)
FCFuncElement("Log2", COMSingle::Log2)
FCFuncElement("Log10", COMSingle::Log10)
Expand Down
36 changes: 36 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Math.cs
Expand Up @@ -49,6 +49,10 @@ public static partial class Math

private const double SCALEB_C3 = 9007199254740992; // 0x1p53

private const int ILogB_NaN = 0x7fffffff;

private const int ILogB_Zero = (-1 - 0x7fffffff);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static short Abs(short value)
{
Expand Down Expand Up @@ -788,6 +792,38 @@ public static double IEEERemainder(double x, double y)
}
}

public static int ILogB(double x)
{
// Implementation based on https://git.musl-libc.org/cgit/musl/tree/src/math/ilogb.c

if (double.IsNaN(x))
{
return ILogB_NaN;
}

ulong i = BitConverter.DoubleToUInt64Bits(x);
int e = (int)((i >> 52) & 0x7FF);

if (e == 0)
{
i <<= 12;
if (i == 0)
{
return ILogB_Zero;
}

for (e = -0x3FF; (i >> 63) == 0; e--, i <<= 1) ;
return e;
}

if (e == 0x7FF)
{
return (i << 12) != 0 ? ILogB_Zero : int.MaxValue;
}

return e - 0x3FF;
}

public static double Log(double a, double newBase)
{
if (double.IsNaN(a))
Expand Down
36 changes: 36 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/MathF.cs
Expand Up @@ -43,6 +43,10 @@ public static partial class MathF

private const float SCALEB_C3 = 16777216f; // 0x1p24f

private const int ILogB_NaN = 0x7fffffff;

private const int ILogB_Zero = (-1 - 0x7fffffff);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Abs(float x)
{
Expand Down Expand Up @@ -180,6 +184,38 @@ public static float IEEERemainder(float x, float y)
}
}

public static int ILogB(float x)
{
// Implementation based on https://git.musl-libc.org/cgit/musl/tree/src/math/ilogbf.c

if (float.IsNaN(x))
{
return ILogB_NaN;
}

uint i = BitConverter.SingleToUInt32Bits(x);
int e = (int)((i >> 23) & 0xFF);

if (e == 0)
{
i <<= 9;
if (i == 0)
{
return ILogB_Zero;
}

for (e = -0x7F; (i >> 31) == 0; e--, i <<= 1) ;
return e;
}

if (e == 0xFF)
{
return i << 9 != 0 ? ILogB_Zero : int.MaxValue;
}

return e - 0x7F;
}

public static float Log(float x, float y)
{
if (float.IsNaN(x))
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Runtime.Extensions/tests/System/Math.cs
Expand Up @@ -2796,6 +2796,16 @@ public static void FusedMultiplyAdd(double x, double y, double z, double expecte
[InlineData( 6.5808859910179210, 2)]
[InlineData( 8.8249778270762876, 3)]
[InlineData( double.PositiveInfinity, unchecked((int)(0x7FFFFFFF)))]
[InlineData( -8.066848, 3)]
[InlineData( 4.345240, 2)]
[InlineData( -8.381433, 3)]
[InlineData( -6.531674, 2)]
[InlineData( 9.267057, 3)]
[InlineData( 0.661986, -1)]
[InlineData( -0.406604, -2)]
[InlineData( 0.561760, -1)]
[InlineData( 0.774152, -1)]
[InlineData( -0.678764, -1)]
public static void ILogB(double value, int expectedResult)
{
Assert.Equal(expectedResult, Math.ILogB(value));
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Runtime.Extensions/tests/System/MathF.cs
Expand Up @@ -1063,6 +1063,16 @@ public static void IEEERemainder()
[InlineData(6.58088599f, 2)]
[InlineData(8.82497783f, 3)]
[InlineData(float.PositiveInfinity, unchecked((int)(0x7FFFFFFF)))]
[InlineData(-8.066849f, 3)]
[InlineData(4.345240f, 2)]
[InlineData(-8.381433f, 3)]
[InlineData(-6.531673f, 2)]
[InlineData(9.267057f, 3)]
[InlineData(0.661986f, -1)]
[InlineData(-0.406604f, -2)]
[InlineData(0.561760f, -1)]
[InlineData(0.774152f, -1)]
[InlineData(-0.678764f, -1)]
public static void ILogB(float value, int expectedResult)
{
Assert.Equal(expectedResult, MathF.ILogB(value));
Expand Down
3 changes: 0 additions & 3 deletions src/mono/System.Private.CoreLib/src/System/Math.Mono.cs
Expand Up @@ -82,9 +82,6 @@ public partial class Math
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern double FusedMultiplyAdd(double x, double y, double z);

[MethodImpl(MethodImplOptions.InternalCall)]
public static extern int ILogB(double x);

[MethodImpl(MethodImplOptions.InternalCall)]
public static extern double Log2(double x);

Expand Down
3 changes: 0 additions & 3 deletions src/mono/System.Private.CoreLib/src/System/MathF.Mono.cs
Expand Up @@ -76,9 +76,6 @@ public partial class MathF
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern float FusedMultiplyAdd(float x, float y, float z);

[MethodImpl(MethodImplOptions.InternalCall)]
public static extern int ILogB(float x);

[MethodImpl(MethodImplOptions.InternalCall)]
public static extern float Log2(float x);

Expand Down
2 changes: 0 additions & 2 deletions src/mono/mono/metadata/icall-decl.h
Expand Up @@ -118,10 +118,8 @@ ICALL_EXPORT float ves_icall_System_MathF_Sqrt (float);
ICALL_EXPORT float ves_icall_System_MathF_Tan (float);
ICALL_EXPORT float ves_icall_System_MathF_Tanh (float);
ICALL_EXPORT float ves_icall_System_Math_Abs_single (float);
ICALL_EXPORT gint32 ves_icall_System_Math_ILogB (double);
ICALL_EXPORT double ves_icall_System_Math_Log2 (double);
ICALL_EXPORT double ves_icall_System_Math_FusedMultiplyAdd (double, double, double);
ICALL_EXPORT gint32 ves_icall_System_MathF_ILogB (float);
ICALL_EXPORT float ves_icall_System_MathF_Log2 (float);
ICALL_EXPORT float ves_icall_System_MathF_FusedMultiplyAdd (float, float, float);
ICALL_EXPORT gint32 ves_icall_System_Environment_get_ProcessorCount (void);
Expand Down
2 changes: 0 additions & 2 deletions src/mono/mono/metadata/icall-def-netcore.h
Expand Up @@ -126,7 +126,6 @@ NOHANDLES(ICALL(MATH_7, "Exp", ves_icall_System_Math_Exp))
NOHANDLES(ICALL(MATH_7a, "FMod", ves_icall_System_Math_FMod))
NOHANDLES(ICALL(MATH_8, "Floor", ves_icall_System_Math_Floor))
NOHANDLES(ICALL(MATH_22, "FusedMultiplyAdd", ves_icall_System_Math_FusedMultiplyAdd))
NOHANDLES(ICALL(MATH_23, "ILogB", ves_icall_System_Math_ILogB))
NOHANDLES(ICALL(MATH_9, "Log", ves_icall_System_Math_Log))
NOHANDLES(ICALL(MATH_10, "Log10", ves_icall_System_Math_Log10))
NOHANDLES(ICALL(MATH_24, "Log2", ves_icall_System_Math_Log2))
Expand Down Expand Up @@ -155,7 +154,6 @@ NOHANDLES(ICALL(MATHF_12, "Exp", ves_icall_System_MathF_Exp))
NOHANDLES(ICALL(MATHF_22, "FMod", ves_icall_System_MathF_FMod))
NOHANDLES(ICALL(MATHF_13, "Floor", ves_icall_System_MathF_Floor))
NOHANDLES(ICALL(MATHF_24, "FusedMultiplyAdd", ves_icall_System_MathF_FusedMultiplyAdd))
NOHANDLES(ICALL(MATHF_25, "ILogB", ves_icall_System_MathF_ILogB))
NOHANDLES(ICALL(MATHF_14, "Log", ves_icall_System_MathF_Log))
NOHANDLES(ICALL(MATHF_15, "Log10", ves_icall_System_MathF_Log10))
NOHANDLES(ICALL(MATHF_26, "Log2", ves_icall_System_MathF_Log2))
Expand Down
22 changes: 0 additions & 22 deletions src/mono/mono/metadata/sysmath.c
Expand Up @@ -187,17 +187,6 @@ ves_icall_System_Math_Ceiling (gdouble v)
return ceil (v);
}

gint32
ves_icall_System_Math_ILogB (gdouble x)
{
if (FP_ILOGB0 != INT_MIN && x == 0.0)
return INT_MIN;
if (FP_ILOGBNAN != INT_MAX && isnan(x))
return INT_MAX;

return ilogb(x);
}

gdouble
ves_icall_System_Math_Log2 (gdouble x)
{
Expand Down Expand Up @@ -348,17 +337,6 @@ ves_icall_System_MathF_ModF (float x, float *d)
return modff (x, d);
}

gint32
ves_icall_System_MathF_ILogB (float x)
{
if (FP_ILOGB0 != INT_MIN && x == 0.0)
return INT_MIN;
if (FP_ILOGBNAN != INT_MAX && isnan(x))
return INT_MAX;

return ilogbf(x);
}

float
ves_icall_System_MathF_Log2 (float x)
{
Expand Down
26 changes: 0 additions & 26 deletions src/mono/mono/mini/interp/interp.c
Expand Up @@ -6781,19 +6781,6 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
LOCAL_VAR (ip [1], double) = scalbn (LOCAL_VAR (ip [2], double), LOCAL_VAR (ip [3], gint32));
ip += 4;
MINT_IN_BREAK;
MINT_IN_CASE(MINT_ILOGB) {
int result;
double x = LOCAL_VAR (ip [2], double);
if (FP_ILOGB0 != INT_MIN && x == 0.0)
result = INT_MIN;
else if (FP_ILOGBNAN != INT_MAX && isnan(x))
result = INT_MAX;
else
result = ilogb (x);
LOCAL_VAR (ip [1], gint32) = result;
ip += 3;
MINT_IN_BREAK;
}

#define MATH_UNOPF(mathfunc) \
LOCAL_VAR (ip [1], float) = mathfunc (LOCAL_VAR (ip [2], float)); \
Expand Down Expand Up @@ -6834,19 +6821,6 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
LOCAL_VAR (ip [1], float) = scalbnf (LOCAL_VAR (ip [2], float), LOCAL_VAR (ip [3], gint32));
ip += 4;
MINT_IN_BREAK;
MINT_IN_CASE(MINT_ILOGBF) {
int result;
float x = LOCAL_VAR (ip [2], float);
if (FP_ILOGB0 != INT_MIN && x == 0.0)
result = INT_MIN;
else if (FP_ILOGBNAN != INT_MAX && isnan(x))
result = INT_MAX;
else
result = ilogbf (x);
LOCAL_VAR (ip [1], gint32) = result;
ip += 3;
MINT_IN_BREAK;
}

MINT_IN_CASE(MINT_INTRINS_ENUM_HASFLAG) {
MonoClass *klass = (MonoClass*)frame->imethod->data_items [ip [4]];
Expand Down
2 changes: 0 additions & 2 deletions src/mono/mono/mini/interp/mintops.def
Expand Up @@ -721,7 +721,6 @@ OPDEF(MINT_COSH, "cosh", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_EXP, "exp", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_FMA, "fma", 5, 1, 3, MintOpNoArgs)
OPDEF(MINT_FLOOR, "floor", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_ILOGB, "ilogb", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_LOG, "log", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_LOG2, "log2", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_LOG10, "log10", 3, 1, 1, MintOpNoArgs)
Expand Down Expand Up @@ -749,7 +748,6 @@ OPDEF(MINT_COSHF, "coshf", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_EXPF, "expf", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_FMAF, "fmaf", 5, 1, 3, MintOpNoArgs)
OPDEF(MINT_FLOORF, "floorf", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_ILOGBF, "ilogbf", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_LOGF, "logf", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_LOG2F, "log2f", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_LOG10F, "log10f", 3, 1, 1, MintOpNoArgs)
Expand Down
2 changes: 0 additions & 2 deletions src/mono/mono/mini/interp/transform.c
Expand Up @@ -2238,8 +2238,6 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas
*op = MINT_EXP;
} else if (strcmp (tm, "Floor") == 0) {
*op = MINT_FLOOR;
} else if (strcmp (tm, "ILogB") == 0) {
*op = MINT_ILOGB;
} else if (tm [0] == 'L') {
if (strcmp (tm, "Log") == 0) {
*op = MINT_LOG;
Expand Down

0 comments on commit 838fed9

Please sign in to comment.