The Labs \ Source Viewer \ SSCLI \ System \ Math

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. **
  17. ** Class:  Math
  18. **
  19. **
  20. ** Purpose: Some floating-point math operations
  21. **
  22. **
  23. ===========================================================*/
  24. namespace System
  25. {
  26.    
  27.     //This class contains only static members and doesn't require serialization.
  28.     using System;
  29.     using System.Runtime.CompilerServices;
  30.     using System.Runtime.ConstrainedExecution;
  31.    
  32.     public static class Math
  33.     {
  34.        
  35.         private static double doubleRoundLimit = 1E+16;
  36.        
  37.         private const int maxRoundingDigits = 15;
  38.        
  39.         // This table is required for the Round function which can specify the number of digits to round to
  40.         private static double[] roundPower10Double = new double[] {1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0,
  41.         10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0, 100000000000000.0, 1E+15};
  42.        
  43.         public const double PI = 3.14159265358979;
  44.         public const double E = 2.71828182845905;
  45.        
  46.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  47.         public static extern double Acos(double d);
  48.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  49.         public static extern double Asin(double d);
  50.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  51.         public static extern double Atan(double d);
  52.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  53.         public static extern double Atan2(double y, double x);
  54.        
  55.         public static decimal Ceiling(decimal d)
  56.         {
  57.             return Decimal.Ceiling(d);
  58.         }
  59.        
  60.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  61.         public static extern double Ceiling(double a);
  62.        
  63.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  64.         public static extern double Cos(double d);
  65.        
  66.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  67.         public static extern double Cosh(double value);
  68.        
  69.         public static decimal Floor(decimal d)
  70.         {
  71.             return Decimal.Floor(d);
  72.         }
  73.        
  74.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  75.         public static extern double Floor(double d);
  76.        
  77.         unsafe private static double InternalRound(double value, int digits, MidpointRounding mode)
  78.         {
  79.             if (Abs(value) < doubleRoundLimit) {
  80.                 double power10 = roundPower10Double[digits];
  81.                 value *= power10;
  82.                 if (mode == MidpointRounding.AwayFromZero) {
  83.                     double fraction = SplitFractionDouble(&value);
  84.                     if (Abs(fraction) >= 0.5) {
  85.                         value += Sign(fraction);
  86.                     }
  87.                 }
  88.                 else {
  89.                     // On X86 this can be inlined to just a few instructions
  90.                     value = Round(value);
  91.                 }
  92.                 value /= power10;
  93.             }
  94.             return value;
  95.         }
  96.        
  97.         unsafe private static double InternalTruncate(double d)
  98.         {
  99.             SplitFractionDouble(&d);
  100.             return d;
  101.         }
  102.        
  103.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  104.         public static extern double Sin(double a);
  105.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  106.         public static extern double Tan(double a);
  107.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  108.         public static extern double Sinh(double value);
  109.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  110.         public static extern double Tanh(double value);
  111.        
  112.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  113.         public static extern double Round(double a);
  114.        
  115.         public static double Round(double value, int digits)
  116.         {
  117.             if ((digits < 0) || (digits > maxRoundingDigits))
  118.                 throw new ArgumentOutOfRangeException("digits", Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits"));
  119.             return InternalRound(value, digits, MidpointRounding.ToEven);
  120.         }
  121.        
  122.         public static double Round(double value, MidpointRounding mode)
  123.         {
  124.             return Round(value, 0, mode);
  125.         }
  126.        
  127.         public static double Round(double value, int digits, MidpointRounding mode)
  128.         {
  129.             if ((digits < 0) || (digits > maxRoundingDigits))
  130.                 throw new ArgumentOutOfRangeException("digits", Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits"));
  131.             if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) {
  132.                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumValue", mode, "MidpointRounding"), "mode");
  133.             }
  134.             return InternalRound(value, digits, mode);
  135.         }
  136.        
  137.         public static decimal Round(decimal d)
  138.         {
  139.             return Decimal.Round(d, 0);
  140.         }
  141.        
  142.         public static decimal Round(decimal d, int decimals)
  143.         {
  144.             return Decimal.Round(d, decimals);
  145.         }
  146.        
  147.         public static decimal Round(decimal d, MidpointRounding mode)
  148.         {
  149.             return Decimal.Round(d, 0, mode);
  150.         }
  151.        
  152.         public static decimal Round(decimal d, int decimals, MidpointRounding mode)
  153.         {
  154.             return Decimal.Round(d, decimals, mode);
  155.         }
  156.        
  157.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  158.         unsafe private static extern double SplitFractionDouble(double* value);
  159.        
  160.         public static decimal Truncate(decimal d)
  161.         {
  162.             return Decimal.Truncate(d);
  163.         }
  164.        
  165.         public static double Truncate(double d)
  166.         {
  167.             return InternalTruncate(d);
  168.         }
  169.        
  170.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  171.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  172.         public static extern double Sqrt(double d);
  173.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  174.         public static extern double Log(double d);
  175.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  176.         public static extern double Log10(double d);
  177.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  178.         public static extern double Exp(double d);
  179.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  180.         public static extern double Pow(double x, double y);
  181.        
  182.         public static double IEEERemainder(double x, double y)
  183.         {
  184.             double regularMod = x % y;
  185.             if (Double.IsNaN(regularMod)) {
  186.                 return Double.NaN;
  187.             }
  188.             if (regularMod == 0) {
  189.                 if (Double.IsNegative(x)) {
  190.                     return Double.NegativeZero;
  191.                 }
  192.             }
  193.             double alternativeResult;
  194.             alternativeResult = regularMod - (Math.Abs(y) * Math.Sign(x));
  195.             if (Math.Abs(alternativeResult) == Math.Abs(regularMod)) {
  196.                 double divisionResult = x / y;
  197.                 double roundedResult = Math.Round(divisionResult);
  198.                 if (Math.Abs(roundedResult) > Math.Abs(divisionResult)) {
  199.                     return alternativeResult;
  200.                 }
  201.                 else {
  202.                     return regularMod;
  203.                 }
  204.             }
  205.             if (Math.Abs(alternativeResult) < Math.Abs(regularMod)) {
  206.                 return alternativeResult;
  207.             }
  208.             else {
  209.                 return regularMod;
  210.             }
  211.         }
  212.        
  213. /*================================Abs=========================================
  214.       **Returns the absolute value of it's argument.
  215.       ============================================================================*/       
  216.         [CLSCompliant(false)]
  217.         public static sbyte Abs(sbyte value)
  218.         {
  219.             if (value >= 0)
  220.                 return value;
  221.             else
  222.                 return AbsHelper(value);
  223.         }
  224.        
  225.         private static sbyte AbsHelper(sbyte value)
  226.         {
  227.             BCLDebug.Assert(value < 0, "AbsHelper should only be called for negative values! (hack for JIT inlining)");
  228.             if (value == SByte.MinValue)
  229.                 throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum"));
  230.             return ((sbyte)(-value));
  231.         }
  232.        
  233.        
  234.         public static short Abs(short value)
  235.         {
  236.             if (value >= 0)
  237.                 return value;
  238.             else
  239.                 return AbsHelper(value);
  240.         }
  241.        
  242.         private static short AbsHelper(short value)
  243.         {
  244.             BCLDebug.Assert(value < 0, "AbsHelper should only be called for negative values! (hack for JIT inlining)");
  245.             if (value == Int16.MinValue)
  246.                 throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum"));
  247.             return (short)-value;
  248.         }
  249.        
  250.         public static int Abs(int value)
  251.         {
  252.             if (value >= 0)
  253.                 return value;
  254.             else
  255.                 return AbsHelper(value);
  256.         }
  257.        
  258.         private static int AbsHelper(int value)
  259.         {
  260.             BCLDebug.Assert(value < 0, "AbsHelper should only be called for negative values! (hack for JIT inlining)");
  261.             if (value == Int32.MinValue)
  262.                 throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum"));
  263.             return -value;
  264.         }
  265.        
  266.         public static long Abs(long value)
  267.         {
  268.             if (value >= 0)
  269.                 return value;
  270.             else
  271.                 return AbsHelper(value);
  272.         }
  273.        
  274.         private static long AbsHelper(long value)
  275.         {
  276.             BCLDebug.Assert(value < 0, "AbsHelper should only be called for negative values! (hack for JIT inlining)");
  277.             if (value == Int64.MinValue)
  278.                 throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum"));
  279.             return -value;
  280.         }
  281.        
  282.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  283.         public static extern float Abs(float value);
  284.         // This is special code to handle NaN (We need to make sure NaN's aren't
  285.         // negated). In CSharp, the else clause here should always be taken if
  286.         // value is NaN, since the normal case is taken if and only if value < 0.
  287.         // To illustrate this completely, a compiler has translated this into:
  288.         // "load value; load 0; bge; ret -value ; ret value".
  289.         // The bge command branches for comparisons with the unordered NaN. So
  290.         // it runs the else case, which returns +value instead of negating it.
  291.         // return (value < 0) ? -value : value;
  292.        
  293.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  294.         public static extern double Abs(double value);
  295.         // This is special code to handle NaN (We need to make sure NaN's aren't
  296.         // negated). In CSharp, the else clause here should always be taken if
  297.         // value is NaN, since the normal case is taken if and only if value < 0.
  298.         // To illustrate this completely, a compiler has translated this into:
  299.         // "load value; load 0; bge; ret -value ; ret value".
  300.         // The bge command branches for comparisons with the unordered NaN. So
  301.         // it runs the else case, which returns +value instead of negating it.
  302.         // return (value < 0) ? -value : value;
  303.        
  304.         public static decimal Abs(decimal value)
  305.         {
  306.             return Decimal.Abs(value);
  307.         }
  308.        
  309. /*================================MAX=========================================
  310.       **Returns the larger of val1 and val2
  311.       ============================================================================*/       
  312.         [CLSCompliant(false)]
  313.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  314.         public static sbyte Max(sbyte val1, sbyte val2)
  315.         {
  316.             return (val1 >= val2) ? val1 : val2;
  317.         }
  318.        
  319.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  320.         public static byte Max(byte val1, byte val2)
  321.         {
  322.             return (val1 >= val2) ? val1 : val2;
  323.         }
  324.        
  325.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  326.         public static short Max(short val1, short val2)
  327.         {
  328.             return (val1 >= val2) ? val1 : val2;
  329.         }
  330.        
  331.         [CLSCompliant(false)]
  332.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  333.         public static ushort Max(ushort val1, ushort val2)
  334.         {
  335.             return (val1 >= val2) ? val1 : val2;
  336.         }
  337.        
  338.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  339.         public static int Max(int val1, int val2)
  340.         {
  341.             return (val1 >= val2) ? val1 : val2;
  342.         }
  343.        
  344.         [CLSCompliant(false)]
  345.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  346.         public static uint Max(uint val1, uint val2)
  347.         {
  348.             return (val1 >= val2) ? val1 : val2;
  349.         }
  350.        
  351.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  352.         public static long Max(long val1, long val2)
  353.         {
  354.             return (val1 >= val2) ? val1 : val2;
  355.         }
  356.        
  357.         [CLSCompliant(false)]
  358.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  359.         public static ulong Max(ulong val1, ulong val2)
  360.         {
  361.             return (val1 >= val2) ? val1 : val2;
  362.         }
  363.        
  364.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  365.         public static float Max(float val1, float val2)
  366.         {
  367.             if (val1 > val2)
  368.                 return val1;
  369.            
  370.             if (Single.IsNaN(val1))
  371.                 return val1;
  372.            
  373.             return val2;
  374.         }
  375.        
  376.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  377.         public static double Max(double val1, double val2)
  378.         {
  379.             if (val1 > val2)
  380.                 return val1;
  381.            
  382.             if (Double.IsNaN(val1))
  383.                 return val1;
  384.            
  385.             return val2;
  386.         }
  387.        
  388.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  389.         public static decimal Max(decimal val1, decimal val2)
  390.         {
  391.             return Decimal.Max(val1, val2);
  392.         }
  393.        
  394. /*================================MIN=========================================
  395.       **Returns the smaller of val1 and val2.
  396.       ============================================================================*/       
  397.         [CLSCompliant(false)]
  398.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  399.         public static sbyte Min(sbyte val1, sbyte val2)
  400.         {
  401.             return (val1 <= val2) ? val1 : val2;
  402.         }
  403.        
  404.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  405.         public static byte Min(byte val1, byte val2)
  406.         {
  407.             return (val1 <= val2) ? val1 : val2;
  408.         }
  409.        
  410.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  411.         public static short Min(short val1, short val2)
  412.         {
  413.             return (val1 <= val2) ? val1 : val2;
  414.         }
  415.        
  416.         [CLSCompliant(false)]
  417.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  418.         public static ushort Min(ushort val1, ushort val2)
  419.         {
  420.             return (val1 <= val2) ? val1 : val2;
  421.         }
  422.        
  423.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  424.         public static int Min(int val1, int val2)
  425.         {
  426.             return (val1 <= val2) ? val1 : val2;
  427.         }
  428.        
  429.         [CLSCompliant(false)]
  430.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  431.         public static uint Min(uint val1, uint val2)
  432.         {
  433.             return (val1 <= val2) ? val1 : val2;
  434.         }
  435.        
  436.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  437.         public static long Min(long val1, long val2)
  438.         {
  439.             return (val1 <= val2) ? val1 : val2;
  440.         }
  441.        
  442.         [CLSCompliant(false)]
  443.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  444.         public static ulong Min(ulong val1, ulong val2)
  445.         {
  446.             return (val1 <= val2) ? val1 : val2;
  447.         }
  448.        
  449.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  450.         public static float Min(float val1, float val2)
  451.         {
  452.             if (val1 < val2)
  453.                 return val1;
  454.            
  455.             if (Single.IsNaN(val1))
  456.                 return val1;
  457.            
  458.             return val2;
  459.         }
  460.        
  461.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  462.         public static double Min(double val1, double val2)
  463.         {
  464.             if (val1 < val2)
  465.                 return val1;
  466.            
  467.             if (Double.IsNaN(val1))
  468.                 return val1;
  469.            
  470.             return val2;
  471.         }
  472.        
  473.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  474.         public static decimal Min(decimal val1, decimal val2)
  475.         {
  476.             return Decimal.Min(val1, val2);
  477.         }
  478.        
  479. /*=====================================Log======================================
  480.       **
  481.       ==============================================================================*/       
  482.         public static double Log(double a, double newBase)
  483.         {
  484.             if (newBase == 1)
  485.                 return Double.NaN;
  486.             if (a != 1 && (newBase == 0 || Double.IsPositiveInfinity(newBase)))
  487.                 return Double.NaN;
  488.            
  489.             return (Log(a) / Log(newBase));
  490.         }
  491.        
  492.        
  493.         // Sign function for VB. Returns -1, 0, or 1 if the sign of the number
  494.         // is negative, 0, or positive. Throws for floating point NaN's.
  495.         [CLSCompliant(false)]
  496.         public static int Sign(sbyte value)
  497.         {
  498.             if (value < 0)
  499.                 return -1;
  500.             else if (value > 0)
  501.                 return 1;
  502.             else
  503.                 return 0;
  504.         }
  505.        
  506.        
  507.         // Sign function for VB. Returns -1, 0, or 1 if the sign of the number
  508.         // is negative, 0, or positive. Throws for floating point NaN's.
  509.         public static int Sign(short value)
  510.         {
  511.             if (value < 0)
  512.                 return -1;
  513.             else if (value > 0)
  514.                 return 1;
  515.             else
  516.                 return 0;
  517.         }
  518.        
  519.         // Sign function for VB. Returns -1, 0, or 1 if the sign of the number
  520.         // is negative, 0, or positive. Throws for floating point NaN's.
  521.         public static int Sign(int value)
  522.         {
  523.             if (value < 0)
  524.                 return -1;
  525.             else if (value > 0)
  526.                 return 1;
  527.             else
  528.                 return 0;
  529.         }
  530.        
  531.         public static int Sign(long value)
  532.         {
  533.             if (value < 0)
  534.                 return -1;
  535.             else if (value > 0)
  536.                 return 1;
  537.             else
  538.                 return 0;
  539.         }
  540.        
  541.         public static int Sign(float value)
  542.         {
  543.             if (value < 0)
  544.                 return -1;
  545.             else if (value > 0)
  546.                 return 1;
  547.             else if (value == 0)
  548.                 return 0;
  549.             throw new ArithmeticException(Environment.GetResourceString("Arithmetic_NaN"));
  550.         }
  551.        
  552.         public static int Sign(double value)
  553.         {
  554.             if (value < 0)
  555.                 return -1;
  556.             else if (value > 0)
  557.                 return 1;
  558.             else if (value == 0)
  559.                 return 0;
  560.             throw new ArithmeticException(Environment.GetResourceString("Arithmetic_NaN"));
  561.         }
  562.        
  563.         public static int Sign(decimal value)
  564.         {
  565.             if (value < 0)
  566.                 return -1;
  567.             else if (value > 0)
  568.                 return 1;
  569.             else
  570.                 return 0;
  571.         }
  572.        
  573.         public static long BigMul(int a, int b)
  574.         {
  575.             return ((long)a) * b;
  576.         }
  577.        
  578.         public static int DivRem(int a, int b, out int result)
  579.         {
  580.             result = a % b;
  581.             return a / b;
  582.         }
  583.        
  584.         public static long DivRem(long a, long b, out long result)
  585.         {
  586.             result = a % b;
  587.             return a / b;
  588.         }
  589.     }
  590. }

Developer Fusion