Advertisement
Guest User

Untitled

a guest
Aug 25th, 2019
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.96 KB | None | 0 0
  1. using System;
  2. using System.Numerics;
  3. using System.Reflection.Emit;
  4.  
  5. namespace TailCallElimination
  6. {
  7. public class Program
  8. {
  9. public static BigInteger Fibonacci(BigInteger n, BigInteger a, BigInteger b)
  10. {
  11. if (n == 0)
  12. return a;
  13. if (n == 1)
  14. return b;
  15.  
  16. return Fibonacci(n - 1, b, a + b);
  17. }
  18.  
  19. static void Main(string[] args)
  20. {
  21. var parameterTypes = new Type[]
  22. {
  23. typeof(BigInteger),
  24. typeof(BigInteger),
  25. typeof(BigInteger)
  26. };
  27.  
  28. var dynamicMethod = new DynamicMethod("Fibonacci", typeof(BigInteger), parameterTypes);
  29.  
  30. var methodIL = dynamicMethod.GetILGenerator();
  31.  
  32. var indexNotZeroLabel = methodIL.DefineLabel();
  33. var indexNotOneLabel = methodIL.DefineLabel();
  34.  
  35. methodIL.Emit(OpCodes.Ldarg_0);
  36. methodIL.Emit(OpCodes.Ldc_I4_0);
  37. methodIL.Emit(OpCodes.Conv_I8);
  38. methodIL.EmitCall(OpCodes.Call, typeof(BigInteger).GetMethod("op_Equality", new Type[] { typeof(BigInteger) , typeof(long) }), null);
  39. methodIL.Emit(OpCodes.Brfalse_S, indexNotZeroLabel);
  40.  
  41. methodIL.Emit(OpCodes.Ldarg_1);
  42. methodIL.Emit(OpCodes.Ret);
  43.  
  44. methodIL.MarkLabel(indexNotZeroLabel);
  45. methodIL.Emit(OpCodes.Ldarg_0);
  46. methodIL.Emit(OpCodes.Ldc_I4_1);
  47. methodIL.Emit(OpCodes.Conv_I8);
  48. methodIL.EmitCall(OpCodes.Call, typeof(BigInteger).GetMethod("op_Equality", new Type[] { typeof(BigInteger), typeof(long) }), null);
  49. methodIL.Emit(OpCodes.Brfalse_S, indexNotOneLabel);
  50.  
  51. methodIL.Emit(OpCodes.Ldarg_2);
  52. methodIL.Emit(OpCodes.Ret);
  53.  
  54. methodIL.MarkLabel(indexNotOneLabel);
  55. methodIL.Emit(OpCodes.Ldarg_0);
  56. methodIL.Emit(OpCodes.Ldc_I4_1);
  57. methodIL.EmitCall(OpCodes.Call, typeof(BigInteger).GetMethod("op_Implicit", new Type[] { typeof(int) }), null);
  58. methodIL.EmitCall(OpCodes.Call, typeof(BigInteger).GetMethod("op_Subtraction"), null);
  59. methodIL.Emit(OpCodes.Ldarg_2);
  60. methodIL.Emit(OpCodes.Ldarg_1);
  61. methodIL.Emit(OpCodes.Ldarg_2);
  62. methodIL.EmitCall(OpCodes.Call, typeof(BigInteger).GetMethod("op_Addition"), null);
  63.  
  64. methodIL.Emit(OpCodes.Tailcall);
  65. methodIL.Emit(OpCodes.Call, dynamicMethod);
  66. methodIL.Emit(OpCodes.Ret);
  67.  
  68. var fibonacci = (Func<BigInteger, BigInteger, BigInteger, BigInteger>)dynamicMethod.CreateDelegate(
  69. typeof(Func<BigInteger, BigInteger, BigInteger, BigInteger>));
  70.  
  71. var n = 8000;
  72.  
  73. Console.WriteLine($"\nDynamic Method(n = {n}): ");
  74.  
  75. var fibonacciNumber = fibonacci(new BigInteger(n), BigInteger.Zero, BigInteger.One);
  76.  
  77. Console.WriteLine($"Result: {fibonacciNumber}");
  78.  
  79. Console.ReadLine();
  80. }
  81. }
  82. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement