Browse Source

Fix #517: Try to reverse constant folding for double and float expressions containing Math.PI and Math.E as factors.

pull/1350/head
Siegfried Pammer 7 years ago
parent
commit
9e71e7fe09
  1. 70
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs
  2. 64
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il
  3. 64
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il
  4. 64
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il
  5. 64
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il
  6. 3
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  7. 273
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

70
ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public class WellKnownConstants
@ -64,5 +66,73 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -64,5 +66,73 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public const decimal DecimalMaxValue = decimal.MaxValue;
public const decimal DecimalMinValue = decimal.MinValue;
public const float Float_PI = (float)Math.PI;
public const float Float_HalfOfPI = (float)Math.PI / 2f;
public const float Float_QuarterOfPI = (float)Math.PI / 4f;
public const float Float_PITimes2 = (float)Math.PI * 2f;
public const float Float_3QuartersOfPI = (float)Math.PI * 3f / 4f;
public const float Float_PIDiv360 = (float)Math.PI / 360f;
public const float Float_PIDiv16 = (float)Math.PI / 16f;
public const float Float_PIDiv32 = (float)Math.PI / 32f;
public const float Float_PIInverseFraction = 1f / (float)Math.PI;
public const float Float_PIInverseFraction2 = 2f / (float)Math.PI;
public const float Float_PIInverseFraction5 = 5f / (float)Math.PI;
public const float Float_PITimes90 = (float)Math.PI * 90f;
public const float Float_PITimes180 = (float)Math.PI * 180f;
public const float Float_LooksLikePI = 3.1415925f;
public const float Float_LooksLikePI2 = 3.14159f;
public const float Float_LooksLikePI3 = 3.141f;
public const float Float_Negated_PI = -(float)Math.PI;
public const float Float_Negated_HalfOfPI = -(float)Math.PI / 2f;
public const float Float_Negated_QuarterOfPI = -(float)Math.PI / 4f;
public const float Float_Negated_PITimes2 = (float)Math.PI * -2f;
public const float Float_Negated_3QuartersOfPI = (float)Math.PI * -3f / 4f;
public const float Float_Negated_PIDiv360 = -(float)Math.PI / 360f;
public const float Float_Negated_PIDiv16 = -(float)Math.PI / 16f;
public const float Float_Negated_PIDiv32 = -(float)Math.PI / 32f;
public const float Float_Negated_PIInverseFraction = -1f / (float)Math.PI;
public const float Float_Negated_PIInverseFraction2 = -2f / (float)Math.PI;
public const float Float_Negated_PIInverseFraction5 = -5f / (float)Math.PI;
public const float Float_Negated_PITimes90 = (float)Math.PI * -90f;
public const float Float_Negated_PITimes180 = (float)Math.PI * -180f;
public const float Float_Negated_LooksLikePI = -3.141f;
public const float Float_E = (float)Math.E;
public const float Float_Negated_E = -(float)Math.E;
public const double Double_PI = Math.PI;
public const double Double_HalfOfPI = Math.PI / 2.0;
public const double Double_QuarterOfPI = Math.PI / 4.0;
public const double Double_PITimes2 = Math.PI * 2.0;
public const double Double_3QuartersOfPI = Math.PI * 3.0 / 4.0;
public const double Double_PIDiv360 = Math.PI / 360.0;
public const double Double_PIDiv16 = Math.PI / 16.0;
public const double Double_PIDiv32 = Math.PI / 32.0;
public const double Double_PIInverseFraction = 1.0 / Math.PI;
public const double Double_PIInverseFraction2 = 2.0 / Math.PI;
public const double Double_PIInverseFraction5 = 5.0 / Math.PI;
public const double Double_PITimes90 = Math.PI * 90.0;
public const double Double_PITimes180 = Math.PI * 180.0;
public const double Double_LooksLikePI = 3.1415926;
public const double Double_LooksLikePI2 = 3.14159;
public const double Double_LooksLikePI3 = 3.141;
public const double Double_Negated_PI = -Math.PI;
public const double Double_Negated_HalfOfPI = -Math.PI / 2.0;
public const double Double_Negated_QuarterOfPI = -Math.PI / 4.0;
public const double Double_Negated_PITimes2 = Math.PI * -2.0;
public const double Double_Negated_3QuartersOfPI = Math.PI * -3.0 / 4.0;
public const double Double_Negated_PIDiv360 = -Math.PI / 360.0;
public const double Double_Negated_PIDiv16 = -Math.PI / 16.0;
public const double Double_Negated_PIDiv32 = -Math.PI / 32.0;
public const double Double_Negated_PIInverseFraction = -1.0 / Math.PI;
public const double Double_Negated_PIInverseFraction2 = -2.0 / Math.PI;
public const double Double_Negated_PIInverseFraction5 = -5.0 / Math.PI;
public const double Double_Negated_PITimes90 = Math.PI * -90.0;
public const double Double_Negated_PITimes180 = Math.PI * -180.0;
public const double Double_Negated_LooksLikePI = -3.141;
public const double Double_E = Math.E;
public const double Double_Negated_E = -Math.E;
}
}

64
ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.il

@ -78,6 +78,70 @@ @@ -78,6 +78,70 @@
uint32,
uint32) = ( 01 00 00 80 FF FF FF FF FF FF FF FF FF FF FF FF
00 00 )
.field public static literal float32 Float_PI = float32(3.1415927)
.field public static literal float32 Float_HalfOfPI = float32(1.5707964)
.field public static literal float32 Float_QuarterOfPI = float32(0.78539819)
.field public static literal float32 Float_PITimes2 = float32(6.2831855)
.field public static literal float32 Float_3QuartersOfPI = float32(2.3561945)
.field public static literal float32 Float_PIDiv360 = float32(8.7266462e-003)
.field public static literal float32 Float_PIDiv16 = float32(0.19634955)
.field public static literal float32 Float_PIDiv32 = float32(9.8174773e-002)
.field public static literal float32 Float_PIInverseFraction = float32(0.31830987)
.field public static literal float32 Float_PIInverseFraction2 = float32(0.63661975)
.field public static literal float32 Float_PIInverseFraction5 = float32(1.5915494)
.field public static literal float32 Float_PITimes90 = float32(282.74335)
.field public static literal float32 Float_PITimes180 = float32(565.48669)
.field public static literal float32 Float_LooksLikePI = float32(3.1415925)
.field public static literal float32 Float_LooksLikePI2 = float32(3.1415901)
.field public static literal float32 Float_LooksLikePI3 = float32(3.141)
.field public static literal float32 Float_Negated_PI = float32(-3.1415927)
.field public static literal float32 Float_Negated_HalfOfPI = float32(-1.5707964)
.field public static literal float32 Float_Negated_QuarterOfPI = float32(-0.78539819)
.field public static literal float32 Float_Negated_PITimes2 = float32(-6.2831855)
.field public static literal float32 Float_Negated_3QuartersOfPI = float32(-2.3561945)
.field public static literal float32 Float_Negated_PIDiv360 = float32(-8.7266462e-003)
.field public static literal float32 Float_Negated_PIDiv16 = float32(-0.19634955)
.field public static literal float32 Float_Negated_PIDiv32 = float32(-9.8174773e-002)
.field public static literal float32 Float_Negated_PIInverseFraction = float32(-0.31830987)
.field public static literal float32 Float_Negated_PIInverseFraction2 = float32(-0.63661975)
.field public static literal float32 Float_Negated_PIInverseFraction5 = float32(-1.5915494)
.field public static literal float32 Float_Negated_PITimes90 = float32(-282.74335)
.field public static literal float32 Float_Negated_PITimes180 = float32(-565.48669)
.field public static literal float32 Float_Negated_LooksLikePI = float32(-3.141)
.field public static literal float32 Float_E = float32(2.7182817)
.field public static literal float32 Float_Negated_E = float32(-2.7182817)
.field public static literal float64 Double_PI = float64(3.1415926535897931)
.field public static literal float64 Double_HalfOfPI = float64(1.5707963267948966)
.field public static literal float64 Double_QuarterOfPI = float64(0.78539816339744828)
.field public static literal float64 Double_PITimes2 = float64(6.2831853071795862)
.field public static literal float64 Double_3QuartersOfPI = float64(2.3561944901923448)
.field public static literal float64 Double_PIDiv360 = float64(8.7266462599716477e-003)
.field public static literal float64 Double_PIDiv16 = float64(0.19634954084936207)
.field public static literal float64 Double_PIDiv32 = float64(9.8174770424681035e-002)
.field public static literal float64 Double_PIInverseFraction = float64(0.31830988618379069)
.field public static literal float64 Double_PIInverseFraction2 = float64(0.63661977236758138)
.field public static literal float64 Double_PIInverseFraction5 = float64(1.5915494309189535)
.field public static literal float64 Double_PITimes90 = float64(282.74333882308139)
.field public static literal float64 Double_PITimes180 = float64(565.48667764616278)
.field public static literal float64 Double_LooksLikePI = float64(3.1415926000000001)
.field public static literal float64 Double_LooksLikePI2 = float64(3.1415899999999999)
.field public static literal float64 Double_LooksLikePI3 = float64(3.141)
.field public static literal float64 Double_Negated_PI = float64(-3.1415926535897931)
.field public static literal float64 Double_Negated_HalfOfPI = float64(-1.5707963267948966)
.field public static literal float64 Double_Negated_QuarterOfPI = float64(-0.78539816339744828)
.field public static literal float64 Double_Negated_PITimes2 = float64(-6.2831853071795862)
.field public static literal float64 Double_Negated_3QuartersOfPI = float64(-2.3561944901923448)
.field public static literal float64 Double_Negated_PIDiv360 = float64(-8.7266462599716477e-003)
.field public static literal float64 Double_Negated_PIDiv16 = float64(-0.19634954084936207)
.field public static literal float64 Double_Negated_PIDiv32 = float64(-9.8174770424681035e-002)
.field public static literal float64 Double_Negated_PIInverseFraction = float64(-0.31830988618379069)
.field public static literal float64 Double_Negated_PIInverseFraction2 = float64(-0.63661977236758138)
.field public static literal float64 Double_Negated_PIInverseFraction5 = float64(-1.5915494309189535)
.field public static literal float64 Double_Negated_PITimes90 = float64(-282.74333882308139)
.field public static literal float64 Double_Negated_PITimes180 = float64(-565.48667764616278)
.field public static literal float64 Double_Negated_LooksLikePI = float64(-3.141)
.field public static literal float64 Double_E = float64(2.7182818284590451)
.field public static literal float64 Double_Negated_E = float64(-2.7182818284590451)
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

64
ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.il

@ -78,6 +78,70 @@ @@ -78,6 +78,70 @@
uint32,
uint32) = ( 01 00 00 80 FF FF FF FF FF FF FF FF FF FF FF FF
00 00 )
.field public static literal float32 Float_PI = float32(3.1415927)
.field public static literal float32 Float_HalfOfPI = float32(1.5707964)
.field public static literal float32 Float_QuarterOfPI = float32(0.78539819)
.field public static literal float32 Float_PITimes2 = float32(6.2831855)
.field public static literal float32 Float_3QuartersOfPI = float32(2.3561945)
.field public static literal float32 Float_PIDiv360 = float32(8.7266462e-003)
.field public static literal float32 Float_PIDiv16 = float32(0.19634955)
.field public static literal float32 Float_PIDiv32 = float32(9.8174773e-002)
.field public static literal float32 Float_PIInverseFraction = float32(0.31830987)
.field public static literal float32 Float_PIInverseFraction2 = float32(0.63661975)
.field public static literal float32 Float_PIInverseFraction5 = float32(1.5915494)
.field public static literal float32 Float_PITimes90 = float32(282.74335)
.field public static literal float32 Float_PITimes180 = float32(565.48669)
.field public static literal float32 Float_LooksLikePI = float32(3.1415925)
.field public static literal float32 Float_LooksLikePI2 = float32(3.1415901)
.field public static literal float32 Float_LooksLikePI3 = float32(3.141)
.field public static literal float32 Float_Negated_PI = float32(-3.1415927)
.field public static literal float32 Float_Negated_HalfOfPI = float32(-1.5707964)
.field public static literal float32 Float_Negated_QuarterOfPI = float32(-0.78539819)
.field public static literal float32 Float_Negated_PITimes2 = float32(-6.2831855)
.field public static literal float32 Float_Negated_3QuartersOfPI = float32(-2.3561945)
.field public static literal float32 Float_Negated_PIDiv360 = float32(-8.7266462e-003)
.field public static literal float32 Float_Negated_PIDiv16 = float32(-0.19634955)
.field public static literal float32 Float_Negated_PIDiv32 = float32(-9.8174773e-002)
.field public static literal float32 Float_Negated_PIInverseFraction = float32(-0.31830987)
.field public static literal float32 Float_Negated_PIInverseFraction2 = float32(-0.63661975)
.field public static literal float32 Float_Negated_PIInverseFraction5 = float32(-1.5915494)
.field public static literal float32 Float_Negated_PITimes90 = float32(-282.74335)
.field public static literal float32 Float_Negated_PITimes180 = float32(-565.48669)
.field public static literal float32 Float_Negated_LooksLikePI = float32(-3.141)
.field public static literal float32 Float_E = float32(2.7182817)
.field public static literal float32 Float_Negated_E = float32(-2.7182817)
.field public static literal float64 Double_PI = float64(3.1415926535897931)
.field public static literal float64 Double_HalfOfPI = float64(1.5707963267948966)
.field public static literal float64 Double_QuarterOfPI = float64(0.78539816339744828)
.field public static literal float64 Double_PITimes2 = float64(6.2831853071795862)
.field public static literal float64 Double_3QuartersOfPI = float64(2.3561944901923448)
.field public static literal float64 Double_PIDiv360 = float64(8.7266462599716477e-003)
.field public static literal float64 Double_PIDiv16 = float64(0.19634954084936207)
.field public static literal float64 Double_PIDiv32 = float64(9.8174770424681035e-002)
.field public static literal float64 Double_PIInverseFraction = float64(0.31830988618379069)
.field public static literal float64 Double_PIInverseFraction2 = float64(0.63661977236758138)
.field public static literal float64 Double_PIInverseFraction5 = float64(1.5915494309189535)
.field public static literal float64 Double_PITimes90 = float64(282.74333882308139)
.field public static literal float64 Double_PITimes180 = float64(565.48667764616278)
.field public static literal float64 Double_LooksLikePI = float64(3.1415926000000001)
.field public static literal float64 Double_LooksLikePI2 = float64(3.1415899999999999)
.field public static literal float64 Double_LooksLikePI3 = float64(3.141)
.field public static literal float64 Double_Negated_PI = float64(-3.1415926535897931)
.field public static literal float64 Double_Negated_HalfOfPI = float64(-1.5707963267948966)
.field public static literal float64 Double_Negated_QuarterOfPI = float64(-0.78539816339744828)
.field public static literal float64 Double_Negated_PITimes2 = float64(-6.2831853071795862)
.field public static literal float64 Double_Negated_3QuartersOfPI = float64(-2.3561944901923448)
.field public static literal float64 Double_Negated_PIDiv360 = float64(-8.7266462599716477e-003)
.field public static literal float64 Double_Negated_PIDiv16 = float64(-0.19634954084936207)
.field public static literal float64 Double_Negated_PIDiv32 = float64(-9.8174770424681035e-002)
.field public static literal float64 Double_Negated_PIInverseFraction = float64(-0.31830988618379069)
.field public static literal float64 Double_Negated_PIInverseFraction2 = float64(-0.63661977236758138)
.field public static literal float64 Double_Negated_PIInverseFraction5 = float64(-1.5915494309189535)
.field public static literal float64 Double_Negated_PITimes90 = float64(-282.74333882308139)
.field public static literal float64 Double_Negated_PITimes180 = float64(-565.48667764616278)
.field public static literal float64 Double_Negated_LooksLikePI = float64(-3.141)
.field public static literal float64 Double_E = float64(2.7182818284590451)
.field public static literal float64 Double_Negated_E = float64(-2.7182818284590451)
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

64
ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.opt.roslyn.il

@ -82,6 +82,70 @@ @@ -82,6 +82,70 @@
uint32,
uint32) = ( 01 00 00 80 FF FF FF FF FF FF FF FF FF FF FF FF
00 00 )
.field public static literal float32 Float_PI = float32(3.1415927)
.field public static literal float32 Float_HalfOfPI = float32(1.5707964)
.field public static literal float32 Float_QuarterOfPI = float32(0.78539819)
.field public static literal float32 Float_PITimes2 = float32(6.2831855)
.field public static literal float32 Float_3QuartersOfPI = float32(2.3561945)
.field public static literal float32 Float_PIDiv360 = float32(8.7266462e-003)
.field public static literal float32 Float_PIDiv16 = float32(0.19634955)
.field public static literal float32 Float_PIDiv32 = float32(9.8174773e-002)
.field public static literal float32 Float_PIInverseFraction = float32(0.31830987)
.field public static literal float32 Float_PIInverseFraction2 = float32(0.63661975)
.field public static literal float32 Float_PIInverseFraction5 = float32(1.5915494)
.field public static literal float32 Float_PITimes90 = float32(282.74335)
.field public static literal float32 Float_PITimes180 = float32(565.48669)
.field public static literal float32 Float_LooksLikePI = float32(3.1415925)
.field public static literal float32 Float_LooksLikePI2 = float32(3.1415901)
.field public static literal float32 Float_LooksLikePI3 = float32(3.141)
.field public static literal float32 Float_Negated_PI = float32(-3.1415927)
.field public static literal float32 Float_Negated_HalfOfPI = float32(-1.5707964)
.field public static literal float32 Float_Negated_QuarterOfPI = float32(-0.78539819)
.field public static literal float32 Float_Negated_PITimes2 = float32(-6.2831855)
.field public static literal float32 Float_Negated_3QuartersOfPI = float32(-2.3561945)
.field public static literal float32 Float_Negated_PIDiv360 = float32(-8.7266462e-003)
.field public static literal float32 Float_Negated_PIDiv16 = float32(-0.19634955)
.field public static literal float32 Float_Negated_PIDiv32 = float32(-9.8174773e-002)
.field public static literal float32 Float_Negated_PIInverseFraction = float32(-0.31830987)
.field public static literal float32 Float_Negated_PIInverseFraction2 = float32(-0.63661975)
.field public static literal float32 Float_Negated_PIInverseFraction5 = float32(-1.5915494)
.field public static literal float32 Float_Negated_PITimes90 = float32(-282.74335)
.field public static literal float32 Float_Negated_PITimes180 = float32(-565.48669)
.field public static literal float32 Float_Negated_LooksLikePI = float32(-3.141)
.field public static literal float32 Float_E = float32(2.7182817)
.field public static literal float32 Float_Negated_E = float32(-2.7182817)
.field public static literal float64 Double_PI = float64(3.1415926535897931)
.field public static literal float64 Double_HalfOfPI = float64(1.5707963267948966)
.field public static literal float64 Double_QuarterOfPI = float64(0.78539816339744828)
.field public static literal float64 Double_PITimes2 = float64(6.2831853071795862)
.field public static literal float64 Double_3QuartersOfPI = float64(2.3561944901923448)
.field public static literal float64 Double_PIDiv360 = float64(8.7266462599716477e-003)
.field public static literal float64 Double_PIDiv16 = float64(0.19634954084936207)
.field public static literal float64 Double_PIDiv32 = float64(9.8174770424681035e-002)
.field public static literal float64 Double_PIInverseFraction = float64(0.31830988618379069)
.field public static literal float64 Double_PIInverseFraction2 = float64(0.63661977236758138)
.field public static literal float64 Double_PIInverseFraction5 = float64(1.5915494309189535)
.field public static literal float64 Double_PITimes90 = float64(282.74333882308139)
.field public static literal float64 Double_PITimes180 = float64(565.48667764616278)
.field public static literal float64 Double_LooksLikePI = float64(3.1415926000000001)
.field public static literal float64 Double_LooksLikePI2 = float64(3.1415899999999999)
.field public static literal float64 Double_LooksLikePI3 = float64(3.141)
.field public static literal float64 Double_Negated_PI = float64(-3.1415926535897931)
.field public static literal float64 Double_Negated_HalfOfPI = float64(-1.5707963267948966)
.field public static literal float64 Double_Negated_QuarterOfPI = float64(-0.78539816339744828)
.field public static literal float64 Double_Negated_PITimes2 = float64(-6.2831853071795862)
.field public static literal float64 Double_Negated_3QuartersOfPI = float64(-2.3561944901923448)
.field public static literal float64 Double_Negated_PIDiv360 = float64(-8.7266462599716477e-003)
.field public static literal float64 Double_Negated_PIDiv16 = float64(-0.19634954084936207)
.field public static literal float64 Double_Negated_PIDiv32 = float64(-9.8174770424681035e-002)
.field public static literal float64 Double_Negated_PIInverseFraction = float64(-0.31830988618379069)
.field public static literal float64 Double_Negated_PIInverseFraction2 = float64(-0.63661977236758138)
.field public static literal float64 Double_Negated_PIInverseFraction5 = float64(-1.5915494309189535)
.field public static literal float64 Double_Negated_PITimes90 = float64(-282.74333882308139)
.field public static literal float64 Double_Negated_PITimes180 = float64(-565.48667764616278)
.field public static literal float64 Double_Negated_LooksLikePI = float64(-3.141)
.field public static literal float64 Double_E = float64(2.7182818284590451)
.field public static literal float64 Double_Negated_E = float64(-2.7182818284590451)
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

64
ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.roslyn.il

@ -82,6 +82,70 @@ @@ -82,6 +82,70 @@
uint32,
uint32) = ( 01 00 00 80 FF FF FF FF FF FF FF FF FF FF FF FF
00 00 )
.field public static literal float32 Float_PI = float32(3.1415927)
.field public static literal float32 Float_HalfOfPI = float32(1.5707964)
.field public static literal float32 Float_QuarterOfPI = float32(0.78539819)
.field public static literal float32 Float_PITimes2 = float32(6.2831855)
.field public static literal float32 Float_3QuartersOfPI = float32(2.3561945)
.field public static literal float32 Float_PIDiv360 = float32(8.7266462e-003)
.field public static literal float32 Float_PIDiv16 = float32(0.19634955)
.field public static literal float32 Float_PIDiv32 = float32(9.8174773e-002)
.field public static literal float32 Float_PIInverseFraction = float32(0.31830987)
.field public static literal float32 Float_PIInverseFraction2 = float32(0.63661975)
.field public static literal float32 Float_PIInverseFraction5 = float32(1.5915494)
.field public static literal float32 Float_PITimes90 = float32(282.74335)
.field public static literal float32 Float_PITimes180 = float32(565.48669)
.field public static literal float32 Float_LooksLikePI = float32(3.1415925)
.field public static literal float32 Float_LooksLikePI2 = float32(3.1415901)
.field public static literal float32 Float_LooksLikePI3 = float32(3.141)
.field public static literal float32 Float_Negated_PI = float32(-3.1415927)
.field public static literal float32 Float_Negated_HalfOfPI = float32(-1.5707964)
.field public static literal float32 Float_Negated_QuarterOfPI = float32(-0.78539819)
.field public static literal float32 Float_Negated_PITimes2 = float32(-6.2831855)
.field public static literal float32 Float_Negated_3QuartersOfPI = float32(-2.3561945)
.field public static literal float32 Float_Negated_PIDiv360 = float32(-8.7266462e-003)
.field public static literal float32 Float_Negated_PIDiv16 = float32(-0.19634955)
.field public static literal float32 Float_Negated_PIDiv32 = float32(-9.8174773e-002)
.field public static literal float32 Float_Negated_PIInverseFraction = float32(-0.31830987)
.field public static literal float32 Float_Negated_PIInverseFraction2 = float32(-0.63661975)
.field public static literal float32 Float_Negated_PIInverseFraction5 = float32(-1.5915494)
.field public static literal float32 Float_Negated_PITimes90 = float32(-282.74335)
.field public static literal float32 Float_Negated_PITimes180 = float32(-565.48669)
.field public static literal float32 Float_Negated_LooksLikePI = float32(-3.141)
.field public static literal float32 Float_E = float32(2.7182817)
.field public static literal float32 Float_Negated_E = float32(-2.7182817)
.field public static literal float64 Double_PI = float64(3.1415926535897931)
.field public static literal float64 Double_HalfOfPI = float64(1.5707963267948966)
.field public static literal float64 Double_QuarterOfPI = float64(0.78539816339744828)
.field public static literal float64 Double_PITimes2 = float64(6.2831853071795862)
.field public static literal float64 Double_3QuartersOfPI = float64(2.3561944901923448)
.field public static literal float64 Double_PIDiv360 = float64(8.7266462599716477e-003)
.field public static literal float64 Double_PIDiv16 = float64(0.19634954084936207)
.field public static literal float64 Double_PIDiv32 = float64(9.8174770424681035e-002)
.field public static literal float64 Double_PIInverseFraction = float64(0.31830988618379069)
.field public static literal float64 Double_PIInverseFraction2 = float64(0.63661977236758138)
.field public static literal float64 Double_PIInverseFraction5 = float64(1.5915494309189535)
.field public static literal float64 Double_PITimes90 = float64(282.74333882308139)
.field public static literal float64 Double_PITimes180 = float64(565.48667764616278)
.field public static literal float64 Double_LooksLikePI = float64(3.1415926000000001)
.field public static literal float64 Double_LooksLikePI2 = float64(3.1415899999999999)
.field public static literal float64 Double_LooksLikePI3 = float64(3.141)
.field public static literal float64 Double_Negated_PI = float64(-3.1415926535897931)
.field public static literal float64 Double_Negated_HalfOfPI = float64(-1.5707963267948966)
.field public static literal float64 Double_Negated_QuarterOfPI = float64(-0.78539816339744828)
.field public static literal float64 Double_Negated_PITimes2 = float64(-6.2831853071795862)
.field public static literal float64 Double_Negated_3QuartersOfPI = float64(-2.3561944901923448)
.field public static literal float64 Double_Negated_PIDiv360 = float64(-8.7266462599716477e-003)
.field public static literal float64 Double_Negated_PIDiv16 = float64(-0.19634954084936207)
.field public static literal float64 Double_Negated_PIDiv32 = float64(-9.8174770424681035e-002)
.field public static literal float64 Double_Negated_PIInverseFraction = float64(-0.31830988618379069)
.field public static literal float64 Double_Negated_PIInverseFraction2 = float64(-0.63661977236758138)
.field public static literal float64 Double_Negated_PIInverseFraction5 = float64(-1.5915494309189535)
.field public static literal float64 Double_Negated_PITimes90 = float64(-282.74333882308139)
.field public static literal float64 Double_Negated_PITimes180 = float64(-565.48667764616278)
.field public static literal float64 Double_Negated_LooksLikePI = float64(-3.141)
.field public static literal float64 Double_E = float64(2.7182818284590451)
.field public static literal float64 Double_Negated_E = float64(-2.7182818284590451)
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

3
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1271,7 +1271,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1271,7 +1271,8 @@ namespace ICSharpCode.Decompiler.CSharp
enumDec.AddAnnotation(new MemberResolveResult(null, field));
return enumDec;
}
typeSystemAstBuilder.UseSpecialConstants = !field.DeclaringType.Equals(field.ReturnType);
bool isMathPIOrE = ((field.Name == "PI" || field.Name == "E") && (field.DeclaringType.FullName == "System.Math" || field.DeclaringType.FullName == "System.MathF"));
typeSystemAstBuilder.UseSpecialConstants = !(field.DeclaringType.Equals(field.ReturnType) || isMathPIOrE);
var fieldDecl = typeSystemAstBuilder.ConvertEntity(field);
SetNewModifier(fieldDecl);
if (settings.FixedBuffers && IsFixedField(field, out var elementType, out var elementCount)) {

273
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -713,6 +713,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -713,6 +713,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} else {
if (IsSpecialConstant(type, constantValue, out var expr))
return expr;
if (type.IsKnownType(KnownTypeCode.Double) || type.IsKnownType(KnownTypeCode.Single))
return ConvertFloatingPointLiteral(type, constantValue);
IType literalType = type;
bool smallInteger = type.IsCSharpSmallIntegerType();
if (smallInteger) {
@ -915,9 +917,276 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -915,9 +917,276 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
return new CastExpression(ConvertType(type), new PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)));
}
static bool IsValidFraction(long num, long den)
{
if (!(den > 0 && num != 0))
return false;
if (den == 1 || Math.Abs(num) == 1)
return true;
return Math.Abs(num) < den && new int[] { 2, 3, 5 }.Any(x => den % x == 0);
}
const int MAX_DENOMINATOR = 1000;
const double DOUBLE_THRESHOLD = 1e-10;
const float FLOAT_THRESHOLD = 1e-10f;
Expression ConvertFloatingPointLiteral(IType type, object constantValue)
{
bool isDouble = type.IsKnownType(KnownTypeCode.Double);
ICompilation compilation = type.GetDefinition().Compilation;
Expression expr = null;
if (isDouble) {
if ((double)constantValue >= int.MaxValue || (double)constantValue <= int.MinValue) {
expr = new PrimitiveExpression(constantValue);
}
} else {
if ((float)constantValue >= int.MaxValue || (float)constantValue <= int.MinValue) {
expr = new PrimitiveExpression(constantValue);
}
}
if (expr == null && UseSpecialConstants) {
IType mathType;
if (isDouble)
mathType = compilation.FindType(typeof(Math));
else
mathType = compilation.FindType(new TopLevelTypeName("System", "MathF")).GetDefinition()
?? compilation.FindType(typeof(Math));
expr = TryExtractExpression(mathType, type, constantValue, "PI", isDouble)
?? TryExtractExpression(mathType, type, constantValue, "E", isDouble);
}
if (expr == null) {
(long num, long den) = isDouble
? DoubleFractionApprox((double)constantValue, MAX_DENOMINATOR)
: FloatFractionApprox((float)constantValue, MAX_DENOMINATOR);
if (IsValidFraction(num, den) && Math.Abs(num) != 1 && Math.Abs(den) != 1) {
var left = MakeConstant(type, num);
var right = MakeConstant(type, den);
return new BinaryOperatorExpression(left, BinaryOperatorType.Divide, right).WithoutILInstruction()
.WithRR(new ConstantResolveResult(type, constantValue));
}
}
if (expr == null)
expr = new PrimitiveExpression(constantValue);
if (AddResolveResultAnnotations)
expr.AddAnnotation(new ConstantResolveResult(type, constantValue));
return expr;
}
Expression MakeConstant(IType type, long c)
{
return new PrimitiveExpression(CSharpPrimitiveCast.Cast(type.GetTypeCode(), c, checkForOverflow: true));
}
const float MathF_PI = 3.14159274f;
const float MathF_E = 2.71828175f;
Expression TryExtractExpression(IType mathType, IType type, object literalValue, string memberName, bool isDouble)
{
Expression MakeFieldReference()
{
AstType mathAstType = ConvertType(mathType);
var fieldRef = new MemberReferenceExpression(new TypeReferenceExpression(mathAstType), memberName);
if (AddResolveResultAnnotations)
fieldRef.WithRR(new MemberResolveResult(mathAstType.GetResolveResult(), mathType.GetFields(f => f.Name == memberName).Single()));
if (type.IsKnownType(KnownTypeCode.Double))
return fieldRef;
if (mathType.Name == "MathF")
return fieldRef;
return new CastExpression(ConvertType(type), fieldRef);
}
Expression ExtractExpression(long n, long d)
{
Expression fieldReference = MakeFieldReference();
Expression expr = fieldReference;
if (n != 1) {
if (n == -1) {
expr = new UnaryOperatorExpression(UnaryOperatorType.Minus, expr);
} else {
expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Multiply, MakeConstant(type, n));
}
}
if (d != 1) {
expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Divide, MakeConstant(type, d));
}
if (isDouble) {
if (Math.Abs((double)literalValue - (memberName == "PI" ? Math.PI : Math.E) * n / d) < DOUBLE_THRESHOLD)
return expr;
} else {
float approxValue = (memberName == "PI" ? MathF_PI : MathF_E) * n / d;
float diff = (float)literalValue - approxValue;
if ((float)Math.Abs(diff) < FLOAT_THRESHOLD)
return expr;
}
expr = fieldReference.Detach();
expr = new BinaryOperatorExpression(MakeConstant(type, n), BinaryOperatorType.Divide, expr);
if (d != 1) {
expr = new BinaryOperatorExpression(MakeConstant(type, d), BinaryOperatorType.Multiply, expr);
}
if (isDouble) {
if (Math.Abs((double)literalValue - (n / (d * (memberName == "PI" ? Math.PI : Math.E)))) < DOUBLE_THRESHOLD)
return expr;
} else {
float approxValue = n / (d * (memberName == "PI" ? MathF_PI : MathF_E));
float diff = (float)literalValue - approxValue;
if ((float)Math.Abs(diff) < FLOAT_THRESHOLD)
return expr;
}
return null;
}
(long num, long den) = isDouble
? DoubleFractionApprox((double)literalValue / (memberName == "PI" ? Math.PI : Math.E), MAX_DENOMINATOR)
: FloatFractionApprox((float)literalValue / (memberName == "PI" ? MathF_PI : MathF_E), MAX_DENOMINATOR);
if (IsValidFraction(num, den)) {
return ExtractExpression(num, den);
}
(num, den) = isDouble
? DoubleFractionApprox((double)literalValue * (memberName == "PI" ? Math.PI : Math.E), MAX_DENOMINATOR)
: FloatFractionApprox((float)literalValue * (memberName == "PI" ? MathF_PI : MathF_E), MAX_DENOMINATOR);
if (IsValidFraction(num, den)) {
return ExtractExpression(num, den);
}
return null;
}
#region FractionApprox
// based on https://www.ics.uci.edu/~eppstein/numth/frap.c
// find rational approximation to given real number
// David Eppstein / UC Irvine / 8 Aug 1993
//
// With corrections from Arno Formella, May 2008
//
// usage: a.out r d
// r is real number to approx
// d is the maximum denominator allowed
//
// based on the theory of continued fractions
// if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...)))
// then best approximation is found by truncating this series
// (with some adjustments in the last term).
//
// Note the fraction can be recovered as the first column of the matrix
// ( a1 1 ) ( a2 1 ) ( a3 1 ) ...
// ( 1 0 ) ( 1 0 ) ( 1 0 )
// Instead of keeping the sequence of continued fraction terms,
// we just keep the last partial product of these matrices.
static (long Num, long Den) DoubleFractionApprox(double value, int maxDenominator)
{
if (value > 0x7FFFFFFF)
return (0, 0);
double startValue = value;
if (value < 0)
value = -value;
bool IsValid(long num, long den) => den > 0 && (double)Math.Abs(value - num / (double)den) < DOUBLE_THRESHOLD;
long ai;
long[,] m = new long[2, 2];
m[0, 0] = m[1, 1] = 1;
m[0, 1] = m[1, 0] = 0;
double v = value;
while (m[1, 0] * (ai = (long)v) + m[1, 1] <= maxDenominator) {
long t = m[0, 0] * ai + m[0, 1];
m[0, 1] = m[0, 0];
m[0, 0] = t;
t = m[1, 0] * ai + m[1, 1];
m[1, 1] = m[1, 0];
m[1, 0] = t;
if (v - ai == 0) break;
v = 1 / (v - ai);
if (Math.Abs(v) > long.MaxValue) break; // value cannot be stored in fraction without overflow
}
if (m[1, 0] == 0)
return (0, 0);
if (!IsValid(num: m[0, 0], den: m[1, 0])) {
ai = (maxDenominator - m[1, 1]) / m[1, 0];
m[0, 0] = m[0, 0] * ai + m[0, 1];
m[1, 0] = m[1, 0] * ai + m[1, 1];
}
if (!IsValid(num: m[0, 0], den: m[1, 0]))
return (0, 0);
return ((startValue < 0 ? -m[0, 0] : m[0, 0]), m[1, 0]);
}
static (long Num, long Den) FloatFractionApprox(float value, int maxDenominator)
{
if (value > 0x7FFFFFFF)
return (0, 0);
float startValue = value;
if (value < 0)
value = -value;
bool IsValid(long num, long den) => den > 0 && (float)Math.Abs(value - num / (float)den) < 1e-9f;
long ai;
long[,] m = new long[2, 2];
m[0, 0] = m[1, 1] = 1;
m[0, 1] = m[1, 0] = 0;
float v = value;
while (m[1, 0] * (ai = (long)v) + m[1, 1] <= maxDenominator) {
long t = m[0, 0] * ai + m[0, 1];
m[0, 1] = m[0, 0];
m[0, 0] = t;
t = m[1, 0] * ai + m[1, 1];
m[1, 1] = m[1, 0];
m[1, 0] = t;
if (v - ai == 0) break;
v = 1 / (v - ai);
if (Math.Abs(v) > long.MaxValue) break; // value cannot be stored in fraction without overflow
}
if (m[1, 0] == 0)
return (0, 0);
if (!IsValid(num: m[0, 0], den: m[1, 0])) {
ai = (maxDenominator - m[1, 1]) / m[1, 0];
m[0, 0] = m[0, 0] * ai + m[0, 1];
m[1, 0] = m[1, 0] * ai + m[1, 1];
}
if (!IsValid(num: m[0, 0], den: m[1, 0]))
return (0, 0);
return (startValue < 0 ? -m[0, 0] : m[0, 0], m[1, 0]);
}
#endregion
#endregion
#region Convert Parameter
public ParameterDeclaration ConvertParameter(IParameter parameter)
{

Loading…
Cancel
Save