diff --git a/src/FastExpressionCompiler/FastExpressionCompiler.cs b/src/FastExpressionCompiler/FastExpressionCompiler.cs index 2ee422ec..4bb42329 100644 --- a/src/FastExpressionCompiler/FastExpressionCompiler.cs +++ b/src/FastExpressionCompiler/FastExpressionCompiler.cs @@ -3508,10 +3508,12 @@ private static bool TryEmitPrimitiveValueConvert(Type sourceType, Type targetTyp il.Demit(isChecked ? OpCodes.Conv_Ovf_I8 : OpCodes.Conv_I8); break; case TypeCode.Double: + if (sourceType.IsUnsigned()) + il.Demit(OpCodes.Conv_R_Un); il.Demit(OpCodes.Conv_R8); break; case TypeCode.Single: - if (sourceType == typeof(uint)) + if (sourceType.IsUnsigned()) il.Demit(OpCodes.Conv_R_Un); il.Demit(OpCodes.Conv_R4); break; diff --git a/test/FastExpressionCompiler.UnitTests/UnaryExpressionTests.cs b/test/FastExpressionCompiler.UnitTests/UnaryExpressionTests.cs index 484f3d02..ae277f66 100644 --- a/test/FastExpressionCompiler.UnitTests/UnaryExpressionTests.cs +++ b/test/FastExpressionCompiler.UnitTests/UnaryExpressionTests.cs @@ -28,6 +28,7 @@ public int Run() ArrayLength_compiles(); Convert_compiles(); ConvertChecked_compiles(); + ConvertToFloat(); Increment_Constant_compiles(); Decrement_compiles(); Increment_compiles(); @@ -52,7 +53,7 @@ public int Run() UnaryPlus_compiles(); Unbox_compiles(); - return 27; + return 28; } @@ -95,6 +96,33 @@ public void ConvertChecked_compiles() Asserts.AreEqual(1, result); } + public void ConvertToFloat() + { + var tests = new object[] { + sbyte.MinValue, sbyte.MaxValue, + short.MinValue, short.MaxValue, + int.MinValue, int.MaxValue, + long.MinValue, long.MaxValue, + uint.MaxValue, uint.MaxValue - 1, + ulong.MaxValue, ulong.MaxValue-10000, + ushort.MaxValue, byte.MaxValue, + char.MaxValue, 'a', + true, false, + double.MaxValue, float.MaxValue, (float)float.Epsilon, +#if NET7_0_OR_GREATER + Int128.MaxValue, Int128.MinValue, UInt128.MaxValue, // these use op_Explicit, but there isn't much coverage of that anyway +#endif + }; + foreach (var constant in tests) + { + var toFloat32 = Lambda>(Convert(Constant(constant), typeof(float))); + var toFloat64 = Lambda>(Convert(Constant(constant), typeof(double))); + + Asserts.AreEqual(toFloat32.CompileSys()(), toFloat32.CompileFast(true)(), $"(float){constant.ToCode()}"); + Asserts.AreEqual(toFloat64.CompileSys()(), toFloat64.CompileFast(true)(), $"(double){constant.ToCode()}"); + } + } + public void Increment_Constant_compiles() {