2002-06-08 Martin Baulig <martin@gnome.org>
[mono.git] / mcs / class / corlib / System / Math.cs
index 08e86e2ba192df44178c73766866fe34f9dd397b..b38a67666790ae6e725de3f63b8d39977bbdc050 100644 (file)
@@ -3,19 +3,25 @@
 //
 // Author:
 //   Bob Smith (bob@thestuff.net)
+//   Dan Lewis (dihlewis@yahoo.co.uk)
 //
 // (C) 2001 Bob Smith.  http://www.thestuff.net
 //
 
 using System;
-using System.Runtime.InteropServices;
+using System.Globalization;
+using System.Runtime.CompilerServices;
 
 namespace System
 {
+//     [CLSCompliant(false)]
         public sealed class Math
         {
                 public const double E = 2.7182818284590452354;
                 public const double PI = 3.14159265358979323846;
+
+               private Math () {}
+
                 public static decimal Abs(decimal value)
                 {
                         return (value < 0)? -value: value;
@@ -31,58 +37,61 @@ namespace System
                 public static int Abs(int value)
                 {
                         if (value == Int32.MinValue)
-                                throw new OverflowException("Value is too small.");
+                                throw new OverflowException (Locale.GetText (Locale.GetText ("Value is too small")));
                         return (value < 0)? -value: value;
                 }
                 public static long Abs(long value)
                 {
                         if (value == Int64.MinValue)
-                                throw new OverflowException("Value is too small.");
+                                throw new OverflowException(Locale.GetText ("Value is too small"));
                         return (value < 0)? -value: value;
                 }
+               [CLSCompliant (false)]
                 public static sbyte Abs(sbyte value)
                 {
                         if (value == SByte.MinValue)
-                                throw new OverflowException("Value is too small.");
+                                throw new OverflowException(Locale.GetText ("Value is too small"));
                         return (sbyte)((value < 0)? -value: value);
                 }
                 public static short Abs(short value)
                 {
                         if (value == Int16.MinValue)
-                                throw new OverflowException("Value is too small.");
+                                throw new OverflowException(Locale.GetText ("Value is too small"));
                         return (short)((value < 0)? -value: value);
                 }
-                [ DllImport("libm", EntryPoint="acos") ]
-                private extern static double _Acos(double d);
-                public static double Acos(double d)
-                {
-                        if (d < -1 || d > 1) return Double.NaN;
-                        return Math._Acos(d);
-                }
-                [ DllImport("libm", EntryPoint="asin") ]
-                private extern static double _Asin(double d);
-                public static double Asin(double d)
-                {
-                        if (d < -1 || d > 1) return Double.NaN;
-                        return Math._Asin(d);
-                }
-                [ DllImport("libm", EntryPoint="atan") ]
-                public extern static double Atan(double d);
-                [ DllImport("libm", EntryPoint="atan2") ]
-                public extern static double Atan2(double y, double x);
+
                 public static double Ceiling(double a)
                 {
-                        double b = (double)((long)a);
+                       if (Double.IsNaN(a)){
+                               return Double.NaN;
+                       }
+
+                       if (Double.IsNegativeInfinity(a)){
+                               return Double.NegativeInfinity;
+                       }
+
+                       if (Double.IsPositiveInfinity(a)){
+                               return Double.PositiveInfinity;
+                       }
+
+                       double b = (double)((long)a);
                         return (b < a)? b+1: b;
                 }
-                [ DllImport("libm", EntryPoint="cos") ]
-                public extern static double Cos(double d);
-                [ DllImport("libm", EntryPoint="cosh") ]
-                public extern static double Cosh(double value);
-                [ DllImport("libm", EntryPoint="exp") ]
-                public extern static double Exp(double d);
                 public static double Floor(double d) {
-                   return (double)((long)d) ;
+                       if (Double.IsNaN(d)){
+                               return Double.NaN;
+                       }
+
+                       if (Double.IsNegativeInfinity(d)){
+                               return Double.NegativeInfinity;
+                       }
+
+                       if (Double.IsPositiveInfinity(d)){
+                               return Double.PositiveInfinity;
+                       }
+
+                       double b = (double)((long)d);
+                       return (d < 0 && d != b) ? --b : b;
                 }
                 public static double IEEERemainder(double x, double y)
                 {
@@ -92,28 +101,13 @@ namespace System
                         if (r != 0) return r;
                         return (x > 0)? 0: -0;
                 }
-                [ DllImport("libm", EntryPoint="log") ]
-                private extern static double _Log(double d);
-                public static double Log(double d)
-                {
-                        if (d == 0) return Double.NegativeInfinity;
-                        else if (d < 0) return Double.NaN;
-                        return Math._Log(d);
-                }
                 public static double Log(double a, double newBase)
                 {
                         if (a == 0) return Double.NegativeInfinity;
                         else if (a < 0) return Double.NaN;
-                        return Math._Log(a)/Math._Log(newBase);
-                }
-                [ DllImport("libm", EntryPoint="log10") ]
-                private extern static double _Log10(double d);
-                public static double Log10(double d)
-                {
-                        if (d == 0) return Double.NegativeInfinity;
-                        else if (d < 0) return Double.NaN;
-                        return Math._Log10(d);
+                        return Log(a)/Log(newBase);
                 }
+
                 public static byte Max(byte val1, byte val2)
                 {
                         return (val1 > val2)? val1: val2;
@@ -138,6 +132,8 @@ namespace System
                 {
                         return (val1 > val2)? val1: val2;
                 }
+
+               [CLSCompliant (false)]
                 public static sbyte Max(sbyte val1, sbyte val2)
                 {
                         return (val1 > val2)? val1: val2;
@@ -146,14 +142,20 @@ namespace System
                 {
                         return (val1 > val2)? val1: val2;
                 }
+
+               [CLSCompliant (false)]
                 public static uint Max(uint val1, uint val2)
                 {
                         return (val1 > val2)? val1: val2;
                 }
+
+               [CLSCompliant (false)]
                 public static ulong Max(ulong val1, ulong val2)
                 {
                         return (val1 > val2)? val1: val2;
                 }
+
+               [CLSCompliant (false)]
                 public static ushort Max(ushort val1, ushort val2)
                 {
                         return (val1 > val2)? val1: val2;
@@ -182,6 +184,8 @@ namespace System
                 {
                         return (val1 < val2)? val1: val2;
                 }
+
+               [CLSCompliant (false)]
                 public static sbyte Min(sbyte val1, sbyte val2)
                 {
                         return (val1 < val2)? val1: val2;
@@ -190,25 +194,30 @@ namespace System
                 {
                         return (val1 < val2)? val1: val2;
                 }
+
+               [CLSCompliant (false)]
                 public static uint Min(uint val1, uint val2)
                 {
                         return (val1 < val2)? val1: val2;
                 }
+
+               [CLSCompliant (false)]
                 public static ulong Min(ulong val1, ulong val2)
                 {
                         return (val1 < val2)? val1: val2;
                 }
+
+               [CLSCompliant (false)]
                 public static ushort Min(ushort val1, ushort val2)
                 {
                         return (val1 < val2)? val1: val2;
                 }
-                [ DllImport("libm", EntryPoint="pow") ]
-                public extern static double Pow(double x, double y);
+
                 public static decimal Round(decimal d)
                 {
                         decimal r = (decimal)((long)d);
-                        decimal a = d-r;
-                        if (a > .5M) return ++r;
+                        decimal a = Abs (d - r);
+                        if (a > .5M) return (r >= 0 ? ++r : --r);
                         else if (a <.5M) return r;
                         else
                         {
@@ -218,11 +227,12 @@ namespace System
                 }
                 public static decimal Round(decimal d, int decimals)
                 {
-                        long p = 10;
+                        long p = 1;
                         int c;
                         decimal retval = d;
                         if (decimals < 0 || decimals > 15)
-                                throw new ArgumentOutOfRangeException("Value is too small or too big.");
+                                throw new ArgumentOutOfRangeException(Locale.GetText (
+                                       "Value is too small or too big."));
                         else if (decimals == 0)
                                 return Math.Round(d);
                         for (c=0; c<decimals; c++) p*=10;
@@ -234,8 +244,8 @@ namespace System
                 public static double Round(double d)
                 {
                         double r = (double)((long)d);
-                        double a = d-r;
-                        if (a > .5) return ++r;
+                        double a = Abs (d - r);
+                        if (a > .5) return (r >= 0 ? ++r : --r);
                         else if (a <.5) return r;
                         else
                         {
@@ -244,11 +254,12 @@ namespace System
                         }
                 }
                 public static double Round(double value, int digits) {
-                        long p = 10;
+                        long p = 1;
                         int c;
                         double retval = value;
                         if (digits < 0 || digits > 15)
-                                throw new ArgumentOutOfRangeException("Value is too small or too big.");
+                                throw new ArgumentOutOfRangeException(Locale.GetText (
+                                       "Value is too small or too big."));
                         else if (digits == 0)
                                 return Math.Round(value);
                         for (c=0; c<digits; c++) p*=10;
@@ -282,6 +293,8 @@ namespace System
                         if (value > 0) return 1;
                         return (value == 0)? 0: -1;
                 }
+
+               [CLSCompliant (false)]
                 public static int Sign(sbyte value)
                 {
                         if (value > 0) return 1;
@@ -292,20 +305,71 @@ namespace System
                         if (value > 0) return 1;
                         return (value == 0)? 0: -1;
                 }
-                [ DllImport("libm", EntryPoint="sin") ]
-                public extern static double Sin(double a);
-                [ DllImport("libm", EntryPoint="sinh") ]
-                public extern static double Sinh(double value);
-                [ DllImport("libm", EntryPoint="sqrt") ]
-                private extern static double _Sqrt(double d);
-                public static double Sqrt(double d) 
-                {
-                        if (d < 0) return Double.NaN;
-                        return Math._Sqrt(d);
-                }
-                [ DllImport("libm", EntryPoint="tan") ]
-                public extern static double Tan(double a);
-                [ DllImport("libm", EntryPoint="tanh") ]
-                public extern static double Tanh(double value);
+
+               // internal calls 
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Sin (double x);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Cos (double x);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Tan (double x);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Sinh (double x);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Cosh (double x);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Tanh (double x);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Acos (double x);
+               
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Asin (double x);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Atan (double x);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Atan2 (double y, double x);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Exp (double x);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Log (double x);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Log10 (double x);
+
+               public static double Pow (double x, double y) {
+                       if (Double.IsNaN (x) || Double.IsNaN (y))
+                               return Double.NaN;
+                       if (Double.IsNegativeInfinity (x))
+                               if (((int)y & 1) == 1)
+                                       return Double.NegativeInfinity;
+                               else
+                                       return Double.PositiveInfinity;
+                       if (Double.IsPositiveInfinity (x))
+                               if (Double.IsNegativeInfinity (y))
+                                       return 0;
+                               else
+                                       return Double.PositiveInfinity;
+                       if (Double.IsNegativeInfinity (y) || Double.IsPositiveInfinity (y))
+                               return Double.NaN;
+                       
+                       return PowImpl (x, y);
+               }
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double PowImpl (double x, double y);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+                public extern static double Sqrt (double x);
         }
 }