Advertisement
Guest User

Generic Operators with IL code emit

a guest
Aug 18th, 2015
831
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 27.24 KB | None | 0 0
  1. /* Copyright (C) 2007  The Trustees of Indiana University
  2.  *
  3.  * Use, modification and distribution is subject to the Boost Software
  4.  * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5.  * http://www.boost.org/LICENSE_1_0.txt)
  6.  *  
  7.  * Authors: Douglas Gregor
  8.  *          Andrew Lumsdaine
  9.  *          
  10.  * Url:     http://www.osl.iu.edu/research/mpi.net/svn/
  11.  *
  12.  * This file provides the "Operations" class, which contains common
  13.  * reduction operations such as addition and multiplication for any
  14.  * type.
  15.  *
  16.  * This code was heavily influenced by Keith Farmer's
  17.  *   Operator Overloading with Generics
  18.  * at http://www.codeproject.com/csharp/genericoperators.asp
  19.  *
  20.  * All MPI related code removed by John Alexiou. Code retains the dynamic
  21.  * operator generators of
  22.  */
  23. using System;
  24. using System.Reflection;
  25. using System.Reflection.Emit;
  26. using System.Runtime.InteropServices;
  27. using System.Collections.Generic;
  28. using System.Linq;
  29.  
  30. namespace SO
  31. {
  32.  
  33.     /// <summary>
  34.     /// The <c>Operation</c> class provides reduction operations for use with the
  35.     /// reduction collectives.
  36.     /// </summary>
  37.     /// <remarks>
  38.     /// The <c>Operation</c> class is used with the reduction collective communication operations
  39.     /// For example, the <see cref="Add"/> property is a delegate that adds two data of type
  40.     /// <typeparamref name="T"/>, while <see cref="Min"/> returns the minimum of the
  41.     /// two data. The reduction operations provided by this class should be
  42.     /// preferred to hand-written reduction operations (particularly for built-in types)
  43.     /// because it enables additional optimizations in the MPI library.
  44.     /// </remarks>
  45.     /// <typeparam name="T">The type of data used in these operations.</typeparam>
  46.     public class Operation<T>
  47.     {
  48.         #region Function Generators
  49.         /// <summary>
  50.         /// Synthesize a new UnaryFunction associated with a given operation.
  51.         /// </summary>
  52.         /// <param name="name">The name of the function to build, e.g., "add".</arg>
  53.         /// <param name="opCode">The <c>OpCode</c> used for primitive types.</arg>
  54.         /// <param name="methodName">The name of the overloaded function used for class types.</arg>
  55.         /// <returns>Returns a new delegate implementing the given operation.</returns>
  56.         public static Func<T, T> BuildUnaryFunction(string name, OpCode opCode, string methodName)
  57.         {
  58.             return BuildUnaryFunction<T, T>(name, opCode, methodName);
  59.         }
  60.         /// <summary>
  61.         /// Synthesize a new UnaryFunction associated with a given operation.
  62.         /// </summary>
  63.         /// <param name="name">The name of the function to build, e.g., "add".</arg>
  64.         /// <param name="opCode">The <c>OpCode</c> used for primitive types.</arg>
  65.         /// <param name="methodName">The name of the overloaded function used for class types.</arg>
  66.         /// <typeparam name="M">The argument type</typeparam>
  67.         /// <typeparam name="R">The return type</typeparam>      
  68.         /// <returns>Returns a new delegate implementing the given operation.</returns>
  69.         public static Func<M, R> BuildUnaryFunction<M, R>(string name, OpCode opCode, string methodName)
  70.         {
  71.             // Build the new mpiDelegateMethod
  72.             DynamicMethod method=
  73.                 new DynamicMethod(
  74.                     name+":"+typeof(T).ToString(),
  75.                     typeof(R),
  76.                     new Type[] { typeof(M) },
  77.                     typeof(Operation<T>));
  78.  
  79.             ILGenerator generator=method.GetILGenerator();
  80.  
  81.             // Load the arguments onto the stack
  82.             generator.Emit(OpCodes.Ldarg_0);
  83.  
  84.             if(typeof(T).IsPrimitive)
  85.             {
  86.                 // Emit the op-code for primitive types, and we're done.
  87.                 generator.Emit(opCode);
  88.             }
  89.             else
  90.             {
  91.                 // Find the overloaded operator and create a call to it
  92.                 MethodInfo opMethod=typeof(T).GetMethod(methodName, new Type[] { typeof(M) });
  93.                 if(opMethod!=null)
  94.                 {
  95.                     generator.EmitCall(OpCodes.Call, opMethod, null);
  96.                 }
  97.                 else
  98.                 {
  99.                     throw new MissingMemberException(
  100.                         string.Format("Method {0}({1}) Not Found.",
  101.                         methodName,
  102.                         typeof(T).Name));
  103.                 }
  104.             }
  105.  
  106.             // Return the intermediate
  107.             generator.Emit(OpCodes.Ret);
  108.  
  109.             // Return a delegate to call the mpiDelegateMethod
  110.             return (Func<M, R>)method.CreateDelegate(typeof(Func<M, R>));
  111.         }
  112.  
  113.         /// <summary>
  114.         /// Synthesize a new UnaryFunction associated with a given operation.
  115.         /// </summary>8
  116.         /// <typeparam name="TArg">The argument type for the function</typeparam>
  117.         /// <arg name="name">The name of the function to build, e.g., "add".</arg>
  118.         /// <arg name="opCode">The <c>OpCode</c> used for primitive types.</arg>
  119.         /// <arg name="methodName">The name of the overloaded function used for class types.</arg>
  120.         /// <returns>Returns a new delegate implementing the given operation.</returns>
  121.         public static Func<TArg, T> BuildConstructor<TArg>()
  122.         {
  123.             // Build the new mpiDelegateMethod
  124.             DynamicMethod method=
  125.                 new DynamicMethod(
  126.                     "new:"+typeof(T).ToString(),
  127.                     typeof(T),
  128.                     new Type[] { typeof(TArg) },
  129.                     typeof(Operation<T>));
  130.  
  131.             ILGenerator generator=method.GetILGenerator();
  132.             LocalBuilder local_var=generator.DeclareLocal(typeof(T));
  133.             Label lbl=generator.DefineLabel();
  134.  
  135.             // Find the overloaded operator and create a call to it
  136.             ConstructorInfo opMethod=typeof(T).GetConstructor(new Type[] { typeof(TArg) });
  137.  
  138.             if(opMethod!=null)
  139.             {
  140.  
  141.                 // Load the arguments onto the stack
  142.                 generator.Emit(OpCodes.Ldarg_0);
  143.                 generator.Emit(OpCodes.Newobj, opMethod);
  144.                 generator.Emit(OpCodes.Stloc_0);
  145.                 generator.Emit(OpCodes.Br_S, lbl);
  146.                 generator.MarkLabel(lbl);
  147.                 generator.Emit(OpCodes.Ldloc_0);
  148.             }
  149.             else
  150.             {
  151.                 throw new MissingMemberException(
  152.                     string.Format("Constructor {0}({1}) Not Found.",
  153.                     typeof(T).Name,
  154.                     typeof(TArg).Name));
  155.             }
  156.  
  157.             // Return the intermediate
  158.             generator.Emit(OpCodes.Ret);
  159.  
  160.             // Return a delegate to call the mpiDelegateMethod
  161.             return (Func<TArg, T>)method.CreateDelegate(typeof(Func<TArg, T>));
  162.         }
  163.  
  164.         public static Func<TArg1, TArg2, T> BuildConstructor<TArg1, TArg2>()
  165.         {
  166.             // Build the new mpiDelegateMethod
  167.             DynamicMethod method=
  168.                 new DynamicMethod(
  169.                     "new:"+typeof(T).ToString(),
  170.                     typeof(T),
  171.                     new Type[] { typeof(TArg1), typeof(TArg2) },
  172.                     typeof(Operation<T>));
  173.  
  174.             ILGenerator generator=method.GetILGenerator();
  175.             LocalBuilder local_var=generator.DeclareLocal(typeof(T));
  176.             Label lbl=generator.DefineLabel();
  177.  
  178.             // Find the overloaded operator and create a call to it
  179.             ConstructorInfo opMethod=typeof(T).GetConstructor(new Type[] { typeof(TArg1), typeof(TArg2) });
  180.  
  181.             if(opMethod!=null)
  182.             {
  183.  
  184.                 // Load the arguments onto the stack
  185.                 generator.Emit(OpCodes.Ldarg_1);
  186.                 generator.Emit(OpCodes.Ldarg_0);
  187.                 generator.Emit(OpCodes.Newobj, opMethod);
  188.                 generator.Emit(OpCodes.Stloc_0);
  189.                 generator.Emit(OpCodes.Br_S, lbl);
  190.                 generator.MarkLabel(lbl);
  191.                 generator.Emit(OpCodes.Ldloc_0);
  192.             }
  193.             else
  194.             {
  195.                 throw new MissingMemberException(
  196.                     string.Format("Constructor {0}({1},{2}) Not Found.",
  197.                     typeof(T).Name,
  198.                     typeof(TArg1).Name,
  199.                     typeof(TArg2).Name));
  200.             }
  201.  
  202.             // Return the intermediate
  203.             generator.Emit(OpCodes.Ret);
  204.  
  205.             // Return a delegate to call the mpiDelegateMethod
  206.             return (Func<TArg1, TArg2, T>)method.CreateDelegate(typeof(Func<TArg1, TArg2, T>));
  207.  
  208.         }
  209.  
  210.         /// <summary>
  211.         /// Synthesize a new BinaryFunction associated with a given operation.
  212.         /// </summary>
  213.         /// <arg name="name">The name of the function to build, e.g., "add".</arg>
  214.         /// <arg name="opCode">The <c>OpCode</c> used for primitive types.</arg>
  215.         /// <arg name="methodName">The name of the overloaded function used for class types.</arg>
  216.         /// <returns>Returns a new delegate implementing the given operation.</returns>
  217.         public static Func<T, T, T> BuildBinaryFunction(string name, OpCode opCode, string methodName)
  218.         {
  219.             // Build the new mpiDelegateMethod
  220.             DynamicMethod method=
  221.                 new DynamicMethod(
  222.                     name+":"+typeof(T).ToString(),
  223.                     typeof(T),
  224.                     new Type[] { typeof(T), typeof(T) },
  225.                     typeof(Operation<T>));
  226.  
  227.             ILGenerator generator=method.GetILGenerator();
  228.  
  229.             // Load the arguments onto the stack
  230.             generator.Emit(OpCodes.Ldarg_0);
  231.             generator.Emit(OpCodes.Ldarg_1);
  232.  
  233.             if(typeof(T).IsPrimitive)
  234.             {
  235.                 // Emit the op-code for primitive types, and we're done.
  236.                 generator.Emit(opCode);
  237.             }
  238.             else
  239.             {
  240.                 // Find the overloaded operator and create a call to it
  241.                 MethodInfo opMethod=typeof(T).GetMethod(methodName, new Type[] { typeof(T), typeof(T) });
  242.                 if(opMethod!=null)
  243.                 {
  244.                     generator.EmitCall(OpCodes.Call, opMethod, null);
  245.                 }
  246.                 else
  247.                 {
  248.                     throw new MissingMemberException(
  249.                         string.Format("Method {0}({1},{2}) Not Found.",
  250.                         methodName,
  251.                         typeof(T).Name,
  252.                         typeof(T).Name));
  253.                 }
  254.             }
  255.  
  256.             // Return the intermediate
  257.             generator.Emit(OpCodes.Ret);
  258.  
  259.             // Return a delegate to call the mpiDelegateMethod
  260.             return (Func<T, T, T>)method.CreateDelegate(typeof(Func<T, T, T>));
  261.         }
  262.  
  263.         public static Func<T, T, R> BuildBinaryFunction<R>(string name, OpCode opCode, string methodName)
  264.         {
  265.             // Build the new mpiDelegateMethod
  266.             DynamicMethod method=
  267.                 new DynamicMethod(
  268.                     name+":"+typeof(T).ToString(),
  269.                     typeof(R),
  270.                     new Type[] { typeof(T), typeof(T) },
  271.                     typeof(Operation<T>));
  272.  
  273.             ILGenerator generator=method.GetILGenerator();
  274.  
  275.             // Load the arguments onto the stack
  276.             generator.Emit(OpCodes.Ldarg_0);
  277.             generator.Emit(OpCodes.Ldarg_1);
  278.  
  279.             if(typeof(T).IsPrimitive)
  280.             {
  281.                 // Emit the op-code for primitive types, and we're done.
  282.                 generator.Emit(opCode);
  283.             }
  284.             else
  285.             {
  286.                 // Find the overloaded operator and create a call to it
  287.                 MethodInfo opMethod=typeof(T).GetMethod(methodName, new Type[] { typeof(T), typeof(T) });
  288.                 if(opMethod!=null)
  289.                 {
  290.                     generator.EmitCall(OpCodes.Call, opMethod, null);
  291.                 }
  292.                 else
  293.                 {
  294.                     throw new MissingMemberException(
  295.                         string.Format("Method {0}({1},{2}) Not Found.",
  296.                         methodName,
  297.                         typeof(T).Name,
  298.                         typeof(T).Name));
  299.                 }
  300.             }
  301.  
  302.             // Return the intermediate
  303.             generator.Emit(OpCodes.Ret);
  304.  
  305.             // Return a delegate to call the mpiDelegateMethod
  306.             return (Func<T, T, R>)method.CreateDelegate(typeof(Func<T, T, R>));
  307.         }
  308.  
  309.         /// <summary>
  310.         /// Synthesize a new BinaryFunction associated with a given operation.
  311.         /// </summary>
  312.         /// <arg name="name">The name of the function to build, e.g., "add".</arg>
  313.         /// <arg name="opCode">The <c>OpCode</c> used for primitive types.</arg>
  314.         /// <arg name="methodName">The name of the overloaded function used for class types.</arg>
  315.         /// <returns>Returns a new delegate implementing the given operation.</returns>
  316.         public static Func<L, R, T> BuildBinaryFunction<L, R>(string name, OpCode opCode, string methodName)
  317.         {
  318.             // Build the new mpiDelegateMethod
  319.             DynamicMethod method=
  320.                 new DynamicMethod(
  321.                     name+":"+typeof(T).ToString(),
  322.                     typeof(T),
  323.                     new Type[] { typeof(L), typeof(R) },
  324.                     typeof(Operation<T>));
  325.  
  326.             ILGenerator generator=method.GetILGenerator();
  327.  
  328.             // Load the arguments onto the stack
  329.             generator.Emit(OpCodes.Ldarg_0);
  330.             generator.Emit(OpCodes.Ldarg_1);
  331.  
  332.             if(typeof(T).IsPrimitive)
  333.             {
  334.                 // Emit the op-code for primitive types, and we're done.
  335.                 generator.Emit(opCode);
  336.             }
  337.             else
  338.             {
  339.                 // Find the overloaded operator and create a call to it
  340.                 MethodInfo opMethod=typeof(T).GetMethod(methodName, new Type[] { typeof(L), typeof(R) });
  341.                 if(opMethod!=null)
  342.                 {
  343.                     generator.EmitCall(OpCodes.Call, opMethod, null);
  344.                 }
  345.                 else
  346.                 {
  347.                     throw new MissingMemberException(
  348.                         string.Format("Method {0}({1},{2}) Not Found.",
  349.                         methodName,
  350.                         typeof(L).Name,
  351.                         typeof(R).Name));
  352.                 }
  353.             }
  354.  
  355.             // Return the intermediate
  356.             generator.Emit(OpCodes.Ret);
  357.  
  358.             // Return a delegate to call the mpiDelegateMethod
  359.             return (Func<L, R, T>)method.CreateDelegate(typeof(Func<L, R, T>));
  360.         }
  361.  
  362.         #endregion
  363.  
  364.         #region Minimum and maximum
  365.         /// <summary>
  366.         /// Cached intermediate of the reduction operation that computes the minimum of
  367.         /// two data.
  368.         /// </summary>
  369.         private static Func<T, T, T> min=null;
  370.  
  371.         /// <summary>
  372.         /// Reduction operation that computes the minimum of two data.
  373.         /// </summary>
  374.         public static Func<T, T, T> Min
  375.         {
  376.             get
  377.             {
  378.                 if(min==null)
  379.                 {
  380.                     // Build the new mpiDelegateMethod
  381.                     DynamicMethod method=
  382.                         new DynamicMethod(
  383.                             "min:"+typeof(T).ToString(),
  384.                             typeof(T),
  385.                             new Type[] { typeof(T), typeof(T) },
  386.                             typeof(Operation<T>));
  387.  
  388.                     ILGenerator generator=method.GetILGenerator();
  389.  
  390.                     // Load the arguments onto the stack
  391.                     generator.Emit(OpCodes.Ldarg_0);
  392.                     generator.Emit(OpCodes.Ldarg_1);
  393.  
  394.                     Label ifLess=generator.DefineLabel();
  395.  
  396.                     if(typeof(T).IsPrimitive)
  397.                         // Compare the two operands with "<" and jump to ifLess if they are equal
  398.                         generator.Emit(OpCodes.Blt_S, ifLess);
  399.                     else
  400.                     {
  401.                         // Find the overloaded "<" operator
  402.                         MethodInfo opMethod=typeof(T).GetMethod("op_LessThan", new Type[] { typeof(T), typeof(T) });
  403.                         if(opMethod==null)
  404.                             throw new ArgumentException("Type "+typeof(T).Name+" does not have a < operator");
  405.  
  406.                         // Create a call to the "<" operator
  407.                         generator.EmitCall(OpCodes.Call, opMethod, null);
  408.  
  409.                         // If the intermediate was "1" (true), jump to ifLess
  410.                         generator.Emit(OpCodes.Brtrue_S, ifLess);
  411.                     }
  412.  
  413.                     // We're in the fall-through case, where the first argument is not less than the second.
  414.  
  415.                     // Load the second argument
  416.                     generator.Emit(OpCodes.Ldarg_1);
  417.  
  418.                     // Return the intermediate
  419.                     generator.Emit(OpCodes.Ret);
  420.  
  421.                     // Label the case where the first argument is less than the second
  422.                     generator.MarkLabel(ifLess);
  423.  
  424.                     // Load the first argument
  425.                     generator.Emit(OpCodes.Ldarg_0);
  426.  
  427.                     // Return the intermediate
  428.                     generator.Emit(OpCodes.Ret);
  429.  
  430.                     // Create the delegate to call the mpiDelegateMethod
  431.                     min=(Func<T, T, T>)method.CreateDelegate(typeof(Func<T, T, T>));
  432.                 }
  433.                 return min;
  434.             }
  435.         }
  436.  
  437.         /// <summary>
  438.         /// Cached intermediate of the reduction operation that computes the maximum of
  439.         /// two data.
  440.         /// </summary>
  441.         private static Func<T, T, T> max=null;
  442.  
  443.         /// <summary>
  444.         /// Reduction operation that computes the maximum of two data.
  445.         /// </summary>
  446.         public static Func<T, T, T> Max
  447.         {
  448.             get
  449.             {
  450.                 if(max==null)
  451.                 {
  452.                     // Build the new mpiDelegateMethod
  453.                     DynamicMethod method=
  454.                         new DynamicMethod(
  455.                             "max:"+typeof(T).ToString(),
  456.                             typeof(T),
  457.                             new Type[] { typeof(T), typeof(T) },
  458.                             typeof(Operation<T>));
  459.  
  460.                     ILGenerator generator=method.GetILGenerator();
  461.  
  462.                     // Load the arguments onto the stack
  463.                     generator.Emit(OpCodes.Ldarg_0);
  464.                     generator.Emit(OpCodes.Ldarg_1);
  465.  
  466.                     Label ifLess=generator.DefineLabel();
  467.  
  468.                     if(typeof(T).IsPrimitive)
  469.                         // Compare the two operands with "<" and jump to ifLess if they are equal
  470.                         generator.Emit(OpCodes.Blt_S, ifLess);
  471.                     else
  472.                     {
  473.                         // Find the overloaded "<" operator
  474.                         MethodInfo opMethod=typeof(T).GetMethod("op_LessThan", new Type[] { typeof(T), typeof(T) });
  475.                         if(opMethod==null)
  476.                             throw new ArgumentException("Type "+typeof(T).Name+" does not have a < operator");
  477.  
  478.                         // Create a call to the "<" operator
  479.                         generator.EmitCall(OpCodes.Call, opMethod, null);
  480.  
  481.                         // If the intermediate was "1" (true), jump to ifLess
  482.                         generator.Emit(OpCodes.Brtrue_S, ifLess);
  483.                     }
  484.  
  485.                     // We're in the fall-through case, where the first argument is not less than the second.
  486.  
  487.                     // Load the first argument
  488.                     generator.Emit(OpCodes.Ldarg_0);
  489.  
  490.                     // Return the intermediate
  491.                     generator.Emit(OpCodes.Ret);
  492.  
  493.                     // Label the case where the first argument is less than the second
  494.                     generator.MarkLabel(ifLess);
  495.  
  496.                     // Load the second argument
  497.                     generator.Emit(OpCodes.Ldarg_1);
  498.  
  499.                     // Return the intermediate
  500.                     generator.Emit(OpCodes.Ret);
  501.  
  502.                     // Create the delegate to call the mpiDelegateMethod
  503.                     max=(Func<T, T, T>)method.CreateDelegate(typeof(Func<T, T, T>));
  504.                 }
  505.                 return max;
  506.             }
  507.         }
  508.         #endregion
  509.  
  510.         #region Arithmetics
  511.         /// <summary>
  512.         /// Cached intermediate of the reduction operation that adds two data.
  513.         /// </summary>
  514.         private static Func<T, T, T> add=null;
  515.  
  516.         /// <summary>
  517.         /// Reduction operation that adds two data.
  518.         /// </summary>
  519.         public static Func<T, T, T> Add
  520.         {
  521.             get
  522.             {
  523.                 if(add==null)
  524.                 {
  525.                     if(typeof(T)==typeof(string))
  526.                         add=BuildBinaryFunction("add", OpCodes.Add, "Concat");
  527.                     else
  528.                         add=BuildBinaryFunction("add", OpCodes.Add, "op_Addition");
  529.                 }
  530.                 return add;
  531.             }
  532.         }
  533.         /// <summary>
  534.         /// Cached intermediate of the reduction operation that subs two data.
  535.         /// </summary>
  536.         private static Func<T, T, T> sub=null;
  537.  
  538.         /// <summary>
  539.         /// Reduction operation that subs two data.
  540.         /// </summary>
  541.         public static Func<T, T, T> Sub
  542.         {
  543.             get
  544.             {
  545.                 if(sub==null)
  546.                 {
  547.                     sub=BuildBinaryFunction("sub", OpCodes.Sub, "op_Subtraction");
  548.                 }
  549.                 return sub;
  550.             }
  551.         }
  552.         /// <summary>
  553.         /// Cached intermediate of the reduction operation that negates a value.
  554.         /// </summary>
  555.         private static Func<T, T> neg=null;
  556.  
  557.         /// <summary>
  558.         /// Reduction operation that negates a value.
  559.         /// </summary>
  560.         public static Func<T, T> Neg
  561.         {
  562.             get
  563.             {
  564.                 if(neg==null)
  565.                 {
  566.                     neg=BuildUnaryFunction("neg", OpCodes.Neg, "op_Negate");
  567.                 }
  568.                 return neg;
  569.             }
  570.         }
  571.  
  572.         /// <summary>
  573.         /// Cached intermediate of the reduction operation that multiplies two data.
  574.         /// </summary>
  575.         private static Func<T, T, T> multiply=null;
  576.  
  577.         /// <summary>
  578.         /// Reduction operation that multiply two data.
  579.         /// </summary>
  580.         public static Func<T, T, T> Mul
  581.         {
  582.             get
  583.             {
  584.                 if(multiply==null)
  585.                     multiply=BuildBinaryFunction("multiply", OpCodes.Mul, "op_Multiply");
  586.                 return multiply;
  587.             }
  588.         }
  589.  
  590.         private static Delegate multiply2=null;
  591.  
  592.         public static Func<L, R, T> BuildMultiply<L, R>()
  593.         {
  594.             if(multiply2==null)
  595.             {
  596.                 multiply2=BuildBinaryFunction<L, R>("multiply", OpCodes.Mul, "op_Multiply");
  597.             }
  598.             return (Func<L, R, T>)multiply2;
  599.         }
  600.  
  601.         /// <summary>
  602.         /// Cached intermediate of the reduction operation that divides two data.
  603.         /// </summary>
  604.         private static Func<T, T, T> div=null;
  605.  
  606.         /// <summary>
  607.         /// Reduction operation that divides two data.
  608.         /// </summary>
  609.         public static Func<T, T, T> Div
  610.         {
  611.             get
  612.             {
  613.                 if(div==null)
  614.                     div=BuildBinaryFunction("div", OpCodes.Div, "op_Divide");
  615.                 return div;
  616.             }
  617.         }
  618.         static Func<T, T, bool> gt=null, lt=null;
  619.         public static Func<T, T, bool> Gt
  620.         {
  621.             get
  622.             {
  623.                 if(gt==null)
  624.                 {
  625.                     gt=BuildBinaryFunction<bool>("gt", OpCodes.Cgt, "op_GreaterThan");
  626.                 }
  627.                 return gt;
  628.             }
  629.         }
  630.         public static Func<T, T, bool> Lt
  631.         {
  632.             get
  633.             {
  634.                 if(lt==null)
  635.                 {
  636.                     lt=BuildBinaryFunction<bool>("lt", OpCodes.Clt, "op_LessThan");
  637.                 }
  638.                 return lt;
  639.             }
  640.         }
  641.  
  642.         #endregion
  643.  
  644.         #region Datatype categorization
  645.         /// <summary>
  646.         /// The kind of MPI datatype. MPI classifies the predefined data types into
  647.         /// several different categories. This classification is used primarily to determine
  648.         /// which predefined reduction operations are supported by the low-level MPI
  649.         /// implementation.
  650.         /// </summary>
  651.         internal enum DatatypeKind
  652.         {
  653.             /// <summary>
  654.             /// C integer types, such as the predefined integral types in C# and .NET.
  655.             /// </summary>
  656.             CInteger,
  657.  
  658.             /// <summary>
  659.             /// Fortran integer types. At present, there are no C# or .NET types that
  660.             /// are classified this way.
  661.             /// </summary>
  662.             FortranInteger,
  663.  
  664.             /// <summary>
  665.             /// Floating point types, such as the predefined <c>float</c> and <c>double</c> types.
  666.             /// </summary>
  667.             FloatingPoint,
  668.  
  669.             /// <summary>
  670.             /// The MPI logical type. At present, there are no C# or .NET types that
  671.             /// are classified this way.
  672.             /// </summary>
  673.             Logical,
  674.  
  675.             /// <summary>
  676.             /// The MPI complex type. At present, there are no C# or .NET types that
  677.             /// are classified this way.
  678.             /// </summary>
  679.             Complex,
  680.  
  681.             /// <summary>
  682.             /// The MPI byte type, which corresponds to the <c>byte</c> type in C#.
  683.             /// </summary>
  684.             Byte,
  685.  
  686.             /// <summary>
  687.             /// Any type that does not fit into one of the other MPI datatype classifications.
  688.             /// </summary>
  689.             Other
  690.         }
  691.  
  692.         ///// <summary>
  693.         ///// The MPI datatype classification of the type <typeparamref name="TEventArgs"/>.
  694.         ///// </summary>
  695.         //internal static DatatypeKind Kind=GetDatatypeKind();
  696.  
  697.         /// <summary>
  698.         ///   Retrieves the kind of datatype for the type <typeparamref name="TEventArgs"/>.
  699.         ///   Used only to initialize <see cref="Kind"/>.
  700.         /// </summary>
  701.         private static DatatypeKind GetDatatypeKind()
  702.         {
  703.             if(!typeof(T).IsPrimitive)
  704.                 // Non-primitive types don'editbox fit any of the MPI datatype categories
  705.                 return DatatypeKind.Other;
  706.  
  707.             // C Integer types
  708.             if(typeof(T)==typeof(short)||typeof(T)==typeof(ushort)
  709.                 ||typeof(T)==typeof(int)||typeof(T)==typeof(uint)
  710.                 ||typeof(T)==typeof(long)||typeof(T)==typeof(ulong))
  711.                 return DatatypeKind.CInteger;
  712.  
  713.             // Floating point types
  714.             if(typeof(T)==typeof(float)||typeof(T)==typeof(double))
  715.                 return DatatypeKind.FloatingPoint;
  716.  
  717.             // Deal with other kinds of types (future?)
  718.             return DatatypeKind.Other;
  719.         }
  720.         #endregion
  721.  
  722.  
  723.     }
  724.  
  725. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement