[eglib] Prefer <langinfo.h> to <localcharset.h>
[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 using System.Runtime.ConstrainedExecution;
36
37 namespace System
38 {
39         public static class Math
40         {
41                 public const double E = 2.7182818284590452354;
42                 public const double PI = 3.14159265358979323846;
43
44                 public static decimal Abs (decimal value)
45                 {
46                         return (value < 0)? -value: value;
47                 }
48
49                 public static double Abs (double value)
50                 {
51                         return (value < 0)? -value: value;
52                 }
53
54                 public static float Abs (float value)
55                 {
56                         return (value < 0)? -value: value;
57                 }
58
59                 public static int Abs (int value)
60                 {
61                         if (value == Int32.MinValue)
62                                 throw new OverflowException (Locale.GetText ("Value is too small."));
63                         return (value < 0)? -value: value;
64                 }
65
66                 public static long Abs (long value)
67                 {
68                         if (value == Int64.MinValue)
69                                 throw new OverflowException (Locale.GetText ("Value is too small."));
70                         return (value < 0)? -value: value;
71                 }
72
73                 [CLSCompliant (false)]
74                 public static sbyte Abs (sbyte value)
75                 {
76                         if (value == SByte.MinValue)
77                                 throw new OverflowException (Locale.GetText ("Value is too small."));
78                         return (sbyte)((value < 0)? -value: value);
79                 }
80
81                 public static short Abs (short value)
82                 {
83                         if (value == Int16.MinValue)
84                                 throw new OverflowException (Locale.GetText ("Value is too small."));
85                         return (short)((value < 0)? -value: value);
86                 }
87
88                 public static decimal Ceiling (decimal d)
89                 {
90                         decimal result = Floor(d);
91                         if (result != d) {
92                                 result++;
93                         }
94                         return result;
95                 }
96
97                 public static double Ceiling (double a)
98                 {
99                         double result = Floor(a);
100                         if (result != a) {
101                                 result++;
102                         }
103                         return result;
104                 }
105
106                 // The following methods are defined in ECMA specs but they are
107                 // not implemented in MS.NET. However, they are in MS.NET 1.1
108
109                 public static long BigMul (int a, int b)
110                 {
111                         return ((long)a * (long)b);
112                 }
113
114                 public static int DivRem (int a, int b, out int result)
115                 {
116                         result = (a % b);
117                         return (int)(a / b);
118                 }
119
120                 public static long DivRem (long a, long b, out long result)
121                 {
122                         result = (a % b);
123                         return (long)(a / b);
124                 }
125
126                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
127                 public extern static double Floor (double d);
128
129                 public static double IEEERemainder (double x, double y)
130                 {
131                         double r;
132                         if (y == 0)
133                                 return Double.NaN;
134                         r = x - (y * Math.Round(x/y));
135                         if (r != 0)
136                                 return r;
137                         /* Int64BitsToDouble is not endian-aware, but that is fine here */
138                         return (x > 0) ? 0: (BitConverter.Int64BitsToDouble (Int64.MinValue));
139                 }
140
141                 public static double Log (double a, double newBase)
142                 {
143                         if (newBase == 1.0)
144                                 return Double.NaN;
145                         double result = Log(a) / Log(newBase);
146                         return (result == -0)? 0: result;
147                 }
148
149                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
150                 public static byte Max (byte val1, byte val2)
151                 {
152                         return (val1 > val2)? val1: val2;
153                 }
154
155                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
156                 public static decimal Max (decimal val1, decimal val2)
157                 {
158                         return (val1 > val2)? val1: val2;
159                 }
160
161                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
162                 public static double Max (double val1, double val2)
163                 {
164                         if (Double.IsNaN (val1) || Double.IsNaN (val2)) {
165                                 return Double.NaN;
166                         }
167                         return (val1 > val2)? val1: val2;
168                 }
169
170                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
171                 public static float Max (float val1, float val2)
172                 {
173                         if (Single.IsNaN (val1) || Single.IsNaN (val2)) {
174                                 return Single.NaN;
175                         }
176                         return (val1 > val2)? val1: val2;
177                 }
178
179                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
180                 public static int Max (int val1, int val2)
181                 {
182                         return (val1 > val2)? val1: val2;
183                 }
184
185                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
186                 public static long Max (long val1, long val2)
187                 {
188                         return (val1 > val2)? val1: val2;
189                 }
190
191                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
192                 [CLSCompliant (false)]
193                 public static sbyte Max (sbyte val1, sbyte val2)
194                 {
195                         return (val1 > val2)? val1: val2;
196                 }
197
198                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
199                 public static short Max (short val1, short val2)
200                 {
201                         return (val1 > val2)? val1: val2;
202                 }
203
204                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
205                 [CLSCompliant (false)]
206                 public static uint Max (uint val1, uint val2)
207                 {
208                         return (val1 > val2)? val1: val2;
209                 }
210
211                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
212                 [CLSCompliant (false)]
213                 public static ulong Max (ulong val1, ulong val2)
214                 {
215                         return (val1 > val2)? val1: val2;
216                 }
217
218                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
219                 [CLSCompliant (false)]
220                 public static ushort Max (ushort val1, ushort val2)
221                 {
222                         return (val1 > val2)? val1: val2;
223                 }
224
225                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
226                 public static byte Min (byte val1, byte val2)
227                 {
228                         return (val1 < val2)? val1: val2;
229                 }
230
231                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
232                 public static decimal Min (decimal val1, decimal val2)
233                 {
234                         return (val1 < val2)? val1: val2;
235                 }
236
237                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
238                 public static double Min (double val1, double val2)
239                 {
240                         if (Double.IsNaN (val1) || Double.IsNaN (val2)) {
241                                 return Double.NaN;
242                         }
243                         return (val1 < val2)? val1: val2;
244                 }
245
246                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
247                 public static float Min (float val1, float val2)
248                 {
249                         if (Single.IsNaN (val1) || Single.IsNaN (val2)) {
250                                 return Single.NaN;
251                         }
252                         return (val1 < val2)? val1: val2;
253                 }
254
255                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
256                 public static int Min (int val1, int val2)
257                 {
258                         return (val1 < val2)? val1: val2;
259                 }
260
261                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
262                 public static long Min (long val1, long val2)
263                 {
264                         return (val1 < val2)? val1: val2;
265                 }
266
267                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
268                 [CLSCompliant (false)]
269                 public static sbyte Min (sbyte val1, sbyte val2)
270                 {
271                         return (val1 < val2)? val1: val2;
272                 }
273
274                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
275                 public static short Min (short val1, short val2)
276                 {
277                         return (val1 < val2)? val1: val2;
278                 }
279
280                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
281                 [CLSCompliant (false)]
282                 public static uint Min (uint val1, uint val2)
283                 {
284                         return (val1 < val2)? val1: val2;
285                 }
286
287                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
288                 [CLSCompliant (false)]
289                 public static ulong Min (ulong val1, ulong val2)
290                 {
291                         return (val1 < val2)? val1: val2;
292                 }
293
294                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
295                 [CLSCompliant (false)]
296                 public static ushort Min (ushort val1, ushort val2)
297                 {
298                         return (val1 < val2)? val1: val2;
299                 }
300
301                 public static decimal Round (decimal d)
302                 {
303                         // Just call Decimal.Round(d, 0); when it rounds well.
304                         decimal int_part = Decimal.Floor(d);
305                         decimal dec_part = d - int_part;
306                         if (((dec_part == 0.5M) &&
307                                 ((2.0M * ((int_part / 2.0M) -
308                                 Decimal.Floor(int_part / 2.0M))) != 0.0M)) ||
309                                 (dec_part > 0.5M)) {
310                                 int_part++;
311                         }
312                         return int_part;
313                 }
314
315                 public static decimal Round (decimal d, int decimals)
316                 {
317                         return Decimal.Round (d, decimals);
318                 }
319
320                 public static decimal Round (decimal d, MidpointRounding mode)
321                 {
322                         if ((mode != MidpointRounding.ToEven) && (mode != MidpointRounding.AwayFromZero))
323                                 throw new ArgumentException ("The value '" + mode + "' is not valid for this usage of the type MidpointRounding.", "mode");
324
325                         if (mode == MidpointRounding.ToEven)
326                                 return Round (d);
327                         else
328                                 return RoundAwayFromZero (d);
329                 }
330
331                 static decimal RoundAwayFromZero (decimal d)
332                 {
333                         decimal int_part = Decimal.Floor(d);
334                         decimal dec_part = d - int_part;
335                         if (int_part >= 0 && dec_part >= 0.5M)
336                                 int_part++;
337                         else if (int_part < 0 && dec_part > 0.5M)
338                                 int_part++;
339                         return int_part;
340                 }
341
342                 public static decimal Round (decimal d, int decimals, MidpointRounding mode)
343                 {
344                         return Decimal.Round (d, decimals, mode);
345                 }
346
347                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
348                 public extern static double Round (double a);
349
350                 public static double Round (double value, int digits)
351                 {
352                         if (digits < 0 || digits > 15)
353                                 throw new ArgumentOutOfRangeException (Locale.GetText ("Value is too small or too big."));
354                         if (digits == 0)
355                                 return Round (value);
356
357                         return Round2(value, digits, false);
358                 }
359
360                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
361                 private extern static double Round2 (double value, int digits, bool away_from_zero);
362
363
364                 public static double Round (double value, MidpointRounding mode)
365                 {
366                         if ((mode != MidpointRounding.ToEven) && (mode != MidpointRounding.AwayFromZero))
367                                 throw new ArgumentException ("The value '" + mode + "' is not valid for this usage of the type MidpointRounding.", "mode");
368
369                         if (mode == MidpointRounding.ToEven)
370                                 return Round (value);
371                         if (value > 0)
372                                 return Floor (value + 0.5);
373                         else
374                                 return Ceiling (value - 0.5);
375                 }
376
377                 public static double Round (double value, int digits, MidpointRounding mode)
378                 {
379                         if ((mode != MidpointRounding.ToEven) && (mode != MidpointRounding.AwayFromZero))
380                                 throw new ArgumentException ("The value '" + mode + "' is not valid for this usage of the type MidpointRounding.", "mode");
381                         if (digits == 0)
382                                 return Round (value, mode);
383
384                         if (mode == MidpointRounding.ToEven)
385                                 return Round (value, digits);
386                         else
387                                 return Round2 (value, digits, true);
388                 }
389                 
390                 public static double Truncate (double d)
391                 {
392                         if (d > 0D)
393                                 return Floor (d);
394                         else if (d < 0D)
395                                 return Ceiling (d);
396                         else
397                                 return d;
398                 }
399
400                 public static decimal Truncate (decimal d)
401                 {
402                         return Decimal.Truncate (d);
403                 }
404
405                 public static decimal Floor (Decimal d)
406                 {
407                         return Decimal.Floor (d);
408                 }
409
410                 public static int Sign (decimal value)
411                 {
412                         if (value > 0) return 1;
413                         return (value == 0)? 0: -1;
414                 }
415
416                 public static int Sign (double value)
417                 {
418                         if (Double.IsNaN (value))
419                                 throw new ArithmeticException ("NAN");
420                         if (value > 0) return 1;
421                         return (value == 0)? 0: -1;
422                 }
423
424                 public static int Sign (float value)
425                 {
426                         if (Single.IsNaN (value))
427                                 throw new ArithmeticException ("NAN");
428                         if (value > 0) return 1;
429                         return (value == 0)? 0: -1;
430                 }
431
432                 public static int Sign (int value)
433                 {
434                         if (value > 0) return 1;
435                         return (value == 0)? 0: -1;
436                 }
437
438                 public static int Sign (long value)
439                 {
440                         if (value > 0) return 1;
441                         return (value == 0)? 0: -1;
442                 }
443
444                 [CLSCompliant (false)]
445                 public static int Sign (sbyte value)
446                 {
447                         if (value > 0) return 1;
448                         return (value == 0)? 0: -1;
449                 }
450
451                 public static int Sign (short value)
452                 {
453                         if (value > 0) return 1;
454                         return (value == 0)? 0: -1;
455                 }
456
457                 // internal calls
458                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
459                 public extern static double Sin (double a);
460
461                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
462                 public extern static double Cos (double d);
463
464                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
465                 public extern static double Tan (double a);
466
467                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
468                 public extern static double Sinh (double value);
469
470                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
471                 public extern static double Cosh (double value);
472
473                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
474                 public extern static double Tanh (double value);
475
476                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
477                 public extern static double Acos (double d);
478                 
479                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
480                 public extern static double Asin (double d);
481
482                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
483                 public extern static double Atan (double d);
484
485                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
486                 public extern static double Atan2 (double y, double x);
487
488                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
489                 public extern static double Exp (double d);
490
491                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
492                 public extern static double Log (double d);
493
494                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
495                 public extern static double Log10 (double d);
496
497                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
498                 public extern static double Pow (double x, double y);
499
500                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
501                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
502                 public extern static double Sqrt (double d);
503         }
504 }