2008-11-28 Miguel De Icaza <miguel@novell.com>
[mono.git] / mcs / class / corlib / System / Math.cs
1 //
2 // System.Math.cs
3 //
4 // Authors:
5 //   Bob Smith (bob@thestuff.net)
6 //   Dan Lewis (dihlewis@yahoo.co.uk)
7 //   Pedro Martínez Juliá (yoros@wanadoo.es)
8 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
9 //
10 // (C) 2001 Bob Smith.  http://www.thestuff.net
11 // Copyright (C) 2003 Pedro Martínez Juliá <yoros@wanadoo.es>
12 // Copyright (C) 2004 Novell (http://www.novell.com)
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System.Runtime.CompilerServices;
35
36 #if NET_2_0
37 using System.Runtime.ConstrainedExecution;
38 #endif
39
40 namespace System
41 {
42 #if NET_2_0
43         public static class Math
44         {
45 #else
46         public sealed class Math
47         {
48                 private Math ()
49                 {
50                 }
51 #endif
52
53                 public const double E = 2.7182818284590452354;
54                 public const double PI = 3.14159265358979323846;
55
56                 public static decimal Abs (decimal value)
57                 {
58                         return (value < 0)? -value: value;
59                 }
60
61                 public static double Abs (double value)
62                 {
63                         return (value < 0)? -value: value;
64                 }
65
66                 public static float Abs (float value)
67                 {
68                         return (value < 0)? -value: value;
69                 }
70
71                 public static int Abs (int value)
72                 {
73                         if (value == Int32.MinValue)
74                                 throw new OverflowException (Locale.GetText ("Value is too small."));
75                         return (value < 0)? -value: value;
76                 }
77
78                 public static long Abs (long value)
79                 {
80                         if (value == Int64.MinValue)
81                                 throw new OverflowException (Locale.GetText ("Value is too small."));
82                         return (value < 0)? -value: value;
83                 }
84
85                 [CLSCompliant (false)]
86                 public static sbyte Abs (sbyte value)
87                 {
88                         if (value == SByte.MinValue)
89                                 throw new OverflowException (Locale.GetText ("Value is too small."));
90                         return (sbyte)((value < 0)? -value: value);
91                 }
92
93                 public static short Abs (short value)
94                 {
95                         if (value == Int16.MinValue)
96                                 throw new OverflowException (Locale.GetText ("Value is too small."));
97                         return (short)((value < 0)? -value: value);
98                 }
99
100 #if NET_2_0
101                 public static decimal Ceiling (decimal d)
102                 {
103                         decimal result = Floor(d);
104                         if (result != d) {
105                                 result++;
106                         }
107                         return result;
108                 }
109 #endif
110
111                 public static double Ceiling (double a)
112                 {
113                         double result = Floor(a);
114                         if (result != a) {
115                                 result++;
116                         }
117                         return result;
118                 }
119
120                 // The following methods are defined in ECMA specs but they are
121                 // not implemented in MS.NET. However, they are in MS.NET 1.1
122
123 #if (!NET_1_0)
124                 public static long BigMul (int a, int b)
125                 {
126                         return ((long)a * (long)b);
127                 }
128
129                 public static int DivRem (int a, int b, out int result)
130                 {
131                         result = (a % b);
132                         return (int)(a / b);
133                 }
134
135                 public static long DivRem (long a, long b, out long result)
136                 {
137                         result = (a % b);
138                         return (long)(a / b);
139                 }
140 #endif
141
142                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
143                 public extern static double Floor (double d);
144
145                 public static double IEEERemainder (double x, double y)
146                 {
147                         double r;
148                         if (y == 0)
149                                 return Double.NaN;
150                         r = x - (y * Math.Round(x/y));
151                         if (r != 0)
152                                 return r;
153                         /* Int64BitsToDouble is not endian-aware, but that is fine here */
154                         return (x > 0) ? 0: (BitConverter.Int64BitsToDouble (Int64.MinValue));
155                 }
156
157                 public static double Log (double a, double newBase)
158                 {
159                         double result = Log(a) / Log(newBase);
160                         return (result == -0)? 0: result;
161                 }
162
163 #if NET_2_0
164                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
165 #endif
166                 public static byte Max (byte val1, byte val2)
167                 {
168                         return (val1 > val2)? val1: val2;
169                 }
170
171 #if NET_2_0
172                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
173 #endif
174                 public static decimal Max (decimal val1, decimal val2)
175                 {
176                         return (val1 > val2)? val1: val2;
177                 }
178
179 #if NET_2_0
180                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
181 #endif
182                 public static double Max (double val1, double val2)
183                 {
184                         if (Double.IsNaN (val1) || Double.IsNaN (val2)) {
185                                 return Double.NaN;
186                         }
187                         return (val1 > val2)? val1: val2;
188                 }
189
190 #if NET_2_0
191                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
192 #endif
193                 public static float Max (float val1, float val2)
194                 {
195                         if (Single.IsNaN (val1) || Single.IsNaN (val2)) {
196                                 return Single.NaN;
197                         }
198                         return (val1 > val2)? val1: val2;
199                 }
200
201 #if NET_2_0
202                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
203 #endif
204                 public static int Max (int val1, int val2)
205                 {
206                         return (val1 > val2)? val1: val2;
207                 }
208
209 #if NET_2_0
210                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
211 #endif
212                 public static long Max (long val1, long val2)
213                 {
214                         return (val1 > val2)? val1: val2;
215                 }
216
217 #if NET_2_0
218                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
219 #endif
220                 [CLSCompliant (false)]
221                 public static sbyte Max (sbyte val1, sbyte val2)
222                 {
223                         return (val1 > val2)? val1: val2;
224                 }
225
226 #if NET_2_0
227                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
228 #endif
229                 public static short Max (short val1, short val2)
230                 {
231                         return (val1 > val2)? val1: val2;
232                 }
233
234 #if NET_2_0
235                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
236 #endif
237                 [CLSCompliant (false)]
238                 public static uint Max (uint val1, uint val2)
239                 {
240                         return (val1 > val2)? val1: val2;
241                 }
242
243 #if NET_2_0
244                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
245 #endif
246                 [CLSCompliant (false)]
247                 public static ulong Max (ulong val1, ulong val2)
248                 {
249                         return (val1 > val2)? val1: val2;
250                 }
251
252 #if NET_2_0
253                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
254 #endif
255                 [CLSCompliant (false)]
256                 public static ushort Max (ushort val1, ushort val2)
257                 {
258                         return (val1 > val2)? val1: val2;
259                 }
260
261 #if NET_2_0
262                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
263 #endif
264                 public static byte Min (byte val1, byte val2)
265                 {
266                         return (val1 < val2)? val1: val2;
267                 }
268
269 #if NET_2_0
270                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
271 #endif
272                 public static decimal Min (decimal val1, decimal val2)
273                 {
274                         return (val1 < val2)? val1: val2;
275                 }
276
277 #if NET_2_0
278                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
279 #endif
280                 public static double Min (double val1, double val2)
281                 {
282                         if (Double.IsNaN (val1) || Double.IsNaN (val2)) {
283                                 return Double.NaN;
284                         }
285                         return (val1 < val2)? val1: val2;
286                 }
287
288 #if NET_2_0
289                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
290 #endif
291                 public static float Min (float val1, float val2)
292                 {
293                         if (Single.IsNaN (val1) || Single.IsNaN (val2)) {
294                                 return Single.NaN;
295                         }
296                         return (val1 < val2)? val1: val2;
297                 }
298
299 #if NET_2_0
300                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
301 #endif
302                 public static int Min (int val1, int val2)
303                 {
304                         return (val1 < val2)? val1: val2;
305                 }
306
307 #if NET_2_0
308                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
309 #endif
310                 public static long Min (long val1, long val2)
311                 {
312                         return (val1 < val2)? val1: val2;
313                 }
314
315 #if NET_2_0
316                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
317 #endif
318                 [CLSCompliant (false)]
319                 public static sbyte Min (sbyte val1, sbyte val2)
320                 {
321                         return (val1 < val2)? val1: val2;
322                 }
323
324 #if NET_2_0
325                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
326 #endif
327                 public static short Min (short val1, short val2)
328                 {
329                         return (val1 < val2)? val1: val2;
330                 }
331
332 #if NET_2_0
333                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
334 #endif
335                 [CLSCompliant (false)]
336                 public static uint Min (uint val1, uint val2)
337                 {
338                         return (val1 < val2)? val1: val2;
339                 }
340
341 #if NET_2_0
342                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
343 #endif
344                 [CLSCompliant (false)]
345                 public static ulong Min (ulong val1, ulong val2)
346                 {
347                         return (val1 < val2)? val1: val2;
348                 }
349
350 #if NET_2_0
351                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
352 #endif
353                 [CLSCompliant (false)]
354                 public static ushort Min (ushort val1, ushort val2)
355                 {
356                         return (val1 < val2)? val1: val2;
357                 }
358
359                 public static decimal Round (decimal d)
360                 {
361                         // Just call Decimal.Round(d, 0); when it rounds well.
362                         decimal int_part = Decimal.Floor(d);
363                         decimal dec_part = d - int_part;
364                         if (((dec_part == 0.5M) &&
365                                 ((2.0M * ((int_part / 2.0M) -
366                                 Decimal.Floor(int_part / 2.0M))) != 0.0M)) ||
367                                 (dec_part > 0.5M)) {
368                                 int_part++;
369                         }
370                         return int_part;
371                 }
372
373                 public static decimal Round (decimal d, int decimals)
374                 {
375                         return Decimal.Round (d, decimals);
376                 }
377
378 #if NET_2_0
379                 public static decimal Round (decimal d, MidpointRounding mode)
380                 {
381                         if ((mode != MidpointRounding.ToEven) && (mode != MidpointRounding.AwayFromZero))
382                                 throw new ArgumentException ("The value '" + mode + "' is not valid for this usage of the type MidpointRounding.", "mode");
383
384                         if (mode == MidpointRounding.ToEven)
385                                 return Round (d);
386                         else
387                                 return RoundAwayFromZero (d);
388                 }
389
390                 static decimal RoundAwayFromZero (decimal d)
391                 {
392                         decimal int_part = Decimal.Floor(d);
393                         decimal dec_part = d - int_part;
394                         if (int_part >= 0 && dec_part >= 0.5M)
395                                 int_part++;
396                         else if (int_part < 0 && dec_part > 0.5M)
397                                 int_part++;
398                         return int_part;
399                 }
400
401                 public static decimal Round (decimal d, int decimals, MidpointRounding mode)
402                 {
403                         return Decimal.Round (d, decimals, mode);
404                 }
405 #endif
406
407                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
408                 public extern static double Round (double a);
409
410                 public static double Round (double value, int digits)
411                 {
412                         if (digits < 0 || digits > 15)
413                                 throw new ArgumentOutOfRangeException (Locale.GetText ("Value is too small or too big."));
414
415                         return Round2(value, digits, false);
416                 }
417
418                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
419                 private extern static double Round2 (double value, int digits, bool away_from_zero);
420
421
422 #if NET_2_0
423                 public static double Round (double value, MidpointRounding mode)
424                 {
425                         if ((mode != MidpointRounding.ToEven) && (mode != MidpointRounding.AwayFromZero))
426                                 throw new ArgumentException ("The value '" + mode + "' is not valid for this usage of the type MidpointRounding.", "mode");
427
428                         if (mode == MidpointRounding.ToEven)
429                                 return Round (value);
430                         if (value > 0)
431                                 return Floor (value + 0.5);
432                         else
433                                 return Ceiling (value - 0.5);
434                 }
435
436                 public static double Round (double value, int digits, MidpointRounding mode)
437                 {
438                         if ((mode != MidpointRounding.ToEven) && (mode != MidpointRounding.AwayFromZero))
439                                 throw new ArgumentException ("The value '" + mode + "' is not valid for this usage of the type MidpointRounding.", "mode");
440
441                         if (mode == MidpointRounding.ToEven)
442                                 return Round (value, digits);
443                         else
444                                 return Round2 (value, digits, true);
445                 }
446                 
447                 public static double Truncate (double d)
448                 {
449                         if (d > 0D)
450                                 return Floor (d);
451                         else if (d < 0D)
452                                 return Ceiling (d);
453                         else
454                                 return d;
455                 }
456
457                 public static decimal Truncate (decimal d)
458                 {
459                         return Decimal.Truncate (d);
460                 }
461
462                 public static decimal Floor (Decimal d)
463                 {
464                         return Decimal.Floor (d);
465                 }
466 #endif
467
468                 public static int Sign (decimal value)
469                 {
470                         if (value > 0) return 1;
471                         return (value == 0)? 0: -1;
472                 }
473
474                 public static int Sign (double value)
475                 {
476                         if (Double.IsNaN (value))
477                                 throw new ArithmeticException ("NAN");
478                         if (value > 0) return 1;
479                         return (value == 0)? 0: -1;
480                 }
481
482                 public static int Sign (float value)
483                 {
484                         if (Single.IsNaN (value))
485                                 throw new ArithmeticException ("NAN");
486                         if (value > 0) return 1;
487                         return (value == 0)? 0: -1;
488                 }
489
490                 public static int Sign (int value)
491                 {
492                         if (value > 0) return 1;
493                         return (value == 0)? 0: -1;
494                 }
495
496                 public static int Sign (long value)
497                 {
498                         if (value > 0) return 1;
499                         return (value == 0)? 0: -1;
500                 }
501
502                 [CLSCompliant (false)]
503                 public static int Sign (sbyte value)
504                 {
505                         if (value > 0) return 1;
506                         return (value == 0)? 0: -1;
507                 }
508
509                 public static int Sign (short value)
510                 {
511                         if (value > 0) return 1;
512                         return (value == 0)? 0: -1;
513                 }
514
515                 // internal calls
516                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
517                 public extern static double Sin (double a);
518
519                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
520                 public extern static double Cos (double d);
521
522                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
523                 public extern static double Tan (double a);
524
525                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
526                 public extern static double Sinh (double value);
527
528                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
529                 public extern static double Cosh (double value);
530
531                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
532                 public extern static double Tanh (double value);
533
534                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
535                 public extern static double Acos (double d);
536                 
537                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
538                 public extern static double Asin (double d);
539
540                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
541                 public extern static double Atan (double d);
542
543                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
544                 public extern static double Atan2 (double y, double x);
545
546                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
547                 public extern static double Exp (double d);
548
549                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
550                 public extern static double Log (double d);
551
552                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
553                 public extern static double Log10 (double d);
554
555                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
556                 public extern static double Pow (double x, double y);
557
558                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
559 #if NET_2_0
560                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
561 #endif
562                 public extern static double Sqrt (double d);
563         }
564 }