Implemented overloaded versions of Parse and TryParse functions for BigInteger.
[mono.git] / mcs / class / System.Core / System.Linq.jvm / Math.cs
1 //
2 // Math.cs
3 //
4 // (C) 2008 Mainsoft, Inc. (http://www.mainsoft.com)
5 // (C) 2008 db4objects, Inc. (http://www.db4o.com)
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 //
26
27 using System;
28 using System.Globalization;
29 using System.Linq.Expressions;
30
31 namespace System.Linq.jvm {
32         class Math {
33
34                 public static object Evaluate (object a, object b, Type t, ExpressionType et)
35                 {
36                         TypeCode tc = Type.GetTypeCode (t);
37                         if (tc == TypeCode.Object) {
38                                 if (!t.IsNullable ()) {
39                                         throw new NotImplementedException (
40                                                 string.Format (
41                                                 "Expression with Node type {0} for type {1}",
42                                                 t.FullName,
43                                                 tc));
44
45                                 }
46                                 return EvaluateNullable (a, b, Type.GetTypeCode (t.GetGenericArguments () [0]), et);
47                         }
48                         return Evaluate (a, b, tc, et);
49                 }
50
51                 public static object EvaluateNullable (object a, object b, TypeCode tc, ExpressionType et)
52                 {
53                         object o = null;
54                         if (a == null || b == null) {
55                                 if (tc != TypeCode.Boolean) {
56                                         return null;
57                                 }
58                                 switch (et) {
59                                 case ExpressionType.And:
60                                         o = And (a, b);
61                                         break;
62                                 case ExpressionType.Or:
63                                         o = Or (a, b);
64                                         break;
65                                 case ExpressionType.ExclusiveOr:
66                                         o = ExclusiveOr (a, b);
67                                         break;
68                                 }
69                         } else {
70                                 o = Evaluate (a, b, tc, et);
71                         }
72
73                         return Convert2Nullable (o, tc);
74
75                 }
76
77                 private static object ExclusiveOr (object a, object b)
78                 {
79                         if (a == null || b == null) {
80                                 return null;
81                         }
82                         return (bool) a ^ (bool) b;
83                 }
84
85                 public static object Or (object a, object b)
86                 {
87                         if (a == null) {
88                                 if (b == null || !((bool) b)) {
89                                         return null;
90                                 }
91                                 return true;
92                         }
93
94                         if (b == null) {
95                                 if (a == null || !((bool) a)) {
96                                         return null;
97                                 }
98                                 return true;
99                         }
100
101                         return (bool) a || (bool) b;
102                 }
103
104                 public static object And (object a, object b)
105                 {
106                         if (a == null) {
107                                 if (b == null || (bool) b) {
108                                         return null;
109                                 }
110                                 return false;
111                         }
112
113                         if (b == null) {
114                                 if (a == null || (bool) a) {
115                                         return null;
116                                 }
117                                 return false;
118                         }
119
120                         return (bool) a && (bool) b;
121                 }
122
123                 private static object Convert2Nullable (object o, TypeCode tc)
124                 {
125                         if (o == null) {
126                                 return null;
127                         }
128                         switch (tc) {
129                         case TypeCode.Char:
130                                 return new Nullable<Char> ((Char) o);
131                         case TypeCode.Byte:
132                                 return new Nullable<Byte> ((Byte) o);
133                         case TypeCode.Decimal:
134                                 return new Nullable<Decimal> ((Decimal) o);
135                         case TypeCode.Double:
136                                 return new Nullable<Double> ((Double) o);
137                         case TypeCode.Int16:
138                                 return new Nullable<Int16> ((Int16) o);
139                         case TypeCode.Int32:
140                                 return new Nullable<Int32> ((Int32) o);
141                         case TypeCode.Int64:
142                                 return new Nullable<Int64> ((Int64) o);
143                         case TypeCode.UInt16:
144                                 return new Nullable<UInt16> ((UInt16) o);
145                         case TypeCode.UInt32:
146                                 return new Nullable<UInt32> ((UInt32) o);
147                         case TypeCode.SByte:
148                                 return new Nullable<SByte> ((SByte) o);
149                         case TypeCode.Single:
150                                 return new Nullable<Single> ((Single) o);
151                         case TypeCode.Boolean:
152                                 return new Nullable<Boolean> ((Boolean) o);
153                         }
154
155                         throw new NotImplementedException ();
156                 }
157
158                 public static object Evaluate (object a, object b, TypeCode tc, ExpressionType et)
159                 {
160                         switch (tc) {
161                         case TypeCode.Boolean:
162                                 return Evaluate (Convert.ToBoolean (a), Convert.ToBoolean (b), et);
163                         case TypeCode.Char:
164                                 return Evaluate (Convert.ToChar (a), Convert.ToChar (b), et);
165                         case TypeCode.Byte:
166                                 return unchecked ((Byte) Evaluate (Convert.ToByte (a), Convert.ToByte (b), et));
167                         case TypeCode.Decimal:
168                                 return Evaluate (Convert.ToDecimal (a), Convert.ToDecimal (b), et);
169                         case TypeCode.Double:
170                                 return Evaluate (Convert.ToDouble (a), Convert.ToDouble (b), et);
171                         case TypeCode.Int16:
172                                 return unchecked ((Int16) Evaluate (Convert.ToInt16 (a), Convert.ToInt16 (b), et));
173                         case TypeCode.Int32:
174                                 return Evaluate (Convert.ToInt32 (a), Convert.ToInt32 (b), et);
175                         case TypeCode.Int64:
176                                 return Evaluate (Convert.ToInt64 (a), Convert.ToInt64 (b), et);
177                         case TypeCode.UInt16:
178                                 return unchecked ((UInt16) Evaluate (Convert.ToUInt16 (a), Convert.ToUInt16 (b), et));
179                         case TypeCode.UInt32:
180                                 return Evaluate (Convert.ToUInt32 (a), Convert.ToUInt32 (b), et);
181                         case TypeCode.UInt64:
182                                 return Evaluate (Convert.ToUInt64 (a), Convert.ToUInt64 (b), et);
183                         case TypeCode.SByte:
184                                 return unchecked ((SByte) Evaluate (Convert.ToSByte (a), Convert.ToSByte (b), et));
185                         case TypeCode.Single:
186                                 return Evaluate (Convert.ToSingle (a), Convert.ToSingle (b), et);
187
188                         }
189
190                         throw new NotImplementedException ();
191                 }
192
193                 public static object NegateChecked (object a, TypeCode tc)
194                 {
195                         switch (tc) {
196                         case TypeCode.Char:
197                                 return checked (-Convert.ToChar (a));
198                         case TypeCode.Byte:
199                                 return checked (-Convert.ToByte (a));
200                         case TypeCode.Decimal:
201                                 return checked (-Convert.ToDecimal (a));
202                         case TypeCode.Double:
203                                 return checked (-Convert.ToDouble (a));
204                         case TypeCode.Int16:
205                                 return checked (-Convert.ToInt16 (a));
206                         case TypeCode.Int32:
207                                 return checked (-Convert.ToInt32 (a));
208                         case TypeCode.Int64:
209                                 return checked (-Convert.ToInt64 (a));
210                         case TypeCode.UInt16:
211                                 return checked (-Convert.ToUInt16 (a));
212                         case TypeCode.UInt32:
213                                 return checked (-Convert.ToUInt32 (a));
214                         case TypeCode.SByte:
215                                 return checked (-Convert.ToSByte (a));
216                         case TypeCode.Single:
217                                 return checked (-Convert.ToSingle (a));
218                         }
219
220                         throw new NotImplementedException ();
221                 }
222
223                 static object CreateInstance (Type type, params object [] arguments)
224                 {
225                         return type.GetConstructor (
226                                 (from argument in arguments select argument.GetType ()).ToArray ()).Invoke (arguments);
227                 }
228
229                 public static object ConvertToTypeChecked (object a, Type fromType, Type toType)
230                 {
231                         if (toType.IsNullable ())
232                                 return a == null ? a : CreateInstance (toType,
233                                         ConvertToTypeChecked (a, fromType.GetNotNullableType (), toType.GetNotNullableType ()));
234
235                         if (a == null) {
236                                 if (!toType.IsValueType)
237                                         return a;
238                                 if (fromType.IsNullable ())
239                                         throw new InvalidOperationException ("Nullable object must have a value");
240                         }
241
242                         if (IsType (toType, a)) {
243                                 return a;
244                         }
245
246                         if (Expression.IsPrimitiveConversion (fromType, toType))
247                                 return Convert.ChangeType (a, toType, CultureInfo.CurrentCulture);
248
249                         throw new NotImplementedException (
250                                                         string.Format ("No Convert defined for type {0} ", toType));
251                 }
252
253                 public static object ConvertToTypeUnchecked (object a, Type fromType, Type toType)
254                 {
255                         if (toType.IsNullable ())
256                                 return a == null ? a : CreateInstance (toType,
257                                         ConvertToTypeUnchecked (a, fromType.GetNotNullableType (), toType.GetNotNullableType ()));
258
259                         if (a == null) {
260                                 if (!toType.IsValueType)
261                                         return a;
262                                 if (fromType.IsNullable ())
263                                         throw new InvalidOperationException ("Nullable object must have a value");
264                         }
265
266                         if (IsType (toType, a))
267                                 return a;
268
269                         if (Expression.IsPrimitiveConversion (fromType, toType))
270                                 return Conversion.ConvertPrimitiveUnChecked (fromType, toType, a);
271
272                         throw new NotImplementedException (
273                                                         string.Format ("No Convert defined for type {0} ", toType));
274                 }
275
276                 public static bool IsType (Type t, Object o)
277                 {
278                         return t.IsInstanceOfType (o);
279                 }
280
281                 public static object Negate (object a, TypeCode tc)
282                 {
283                         switch (tc) {
284                         case TypeCode.Char:
285                                 return unchecked (-Convert.ToChar (a));
286                         case TypeCode.Byte:
287                                 return unchecked (-Convert.ToByte (a));
288                         case TypeCode.Decimal:
289                                 return unchecked (-Convert.ToDecimal (a));
290                         case TypeCode.Double:
291                                 return unchecked (-Convert.ToDouble (a));
292                         case TypeCode.Int16:
293                                 return unchecked (-Convert.ToInt16 (a));
294                         case TypeCode.Int32:
295                                 return unchecked (-Convert.ToInt32 (a));
296                         case TypeCode.Int64:
297                                 return unchecked (-Convert.ToInt64 (a));
298                         case TypeCode.UInt16:
299                                 return unchecked (-Convert.ToUInt16 (a));
300                         case TypeCode.UInt32:
301                                 return unchecked (-Convert.ToUInt32 (a));
302                         case TypeCode.SByte:
303                                 return unchecked (-Convert.ToSByte (a));
304                         case TypeCode.Single:
305                                 return unchecked (-Convert.ToSingle (a));
306                         }
307
308                         throw new NotImplementedException ();
309                 }
310
311                 public static object RightShift (object a, int n, TypeCode tc)
312                 {
313                         switch (tc) {
314                         case TypeCode.Int16:
315                                 return Convert.ToInt16 (a) >> n;
316                         case TypeCode.Int32:
317                                 return Convert.ToInt32 (a) >> n;
318                         case TypeCode.Int64:
319                                 return Convert.ToInt64 (a) >> n;
320                         case TypeCode.UInt16:
321                                 return Convert.ToUInt16 (a) >> n;
322                         case TypeCode.UInt32:
323                                 return Convert.ToUInt32 (a) >> n;
324                         case TypeCode.UInt64:
325                                 return Convert.ToUInt64 (a) >> n;
326                         }
327
328                         throw new NotImplementedException ();
329                 }
330
331                 public static object LeftShift (object a, int n, TypeCode tc)
332                 {
333                         switch (tc) {
334                         case TypeCode.Int16:
335                                 return Convert.ToInt16 (a) << n;
336                         case TypeCode.Int32:
337                                 return Convert.ToInt32 (a) << n;
338                         case TypeCode.Int64:
339                                 return Convert.ToInt64 (a) << n;
340                         case TypeCode.UInt16:
341                                 return Convert.ToUInt16 (a) << n;
342                         case TypeCode.UInt32:
343                                 return Convert.ToUInt32 (a) << n;
344                         case TypeCode.UInt64:
345                                 return Convert.ToUInt64 (a) << n;
346                         }
347
348                         throw new NotImplementedException ();
349                 }
350
351                 private static Decimal Evaluate (Decimal a, Decimal b, ExpressionType et)
352                 {
353                         switch (et) {
354                         case ExpressionType.Add:
355                                 return unchecked (a + b);
356                         case ExpressionType.AddChecked:
357                                 return checked (a + b);
358                         case ExpressionType.Subtract:
359                                 return unchecked (a - b);
360                         case ExpressionType.SubtractChecked:
361                                 return checked (a - b);
362                         case ExpressionType.Multiply:
363                                 return unchecked (a * b);
364                         case ExpressionType.MultiplyChecked:
365                                 return checked (a * b);
366                         case ExpressionType.Divide:
367                                 return a / b;
368                         case ExpressionType.Modulo:
369                                 return a % b;
370
371                         }
372
373                         throw new NotImplementedException ();
374                 }
375
376                 private static Double Evaluate (Double a, Double b, ExpressionType et)
377                 {
378                         switch (et) {
379                         case ExpressionType.Add:
380                                 return unchecked (a + b);
381                         case ExpressionType.AddChecked:
382                                 return checked (a + b);
383                         case ExpressionType.Subtract:
384                                 return unchecked (a - b);
385                         case ExpressionType.SubtractChecked:
386                                 return checked (a - b);
387                         case ExpressionType.Multiply:
388                                 return unchecked (a * b);
389                         case ExpressionType.MultiplyChecked:
390                                 return checked (a * b);
391                         case ExpressionType.Divide:
392                                 return a / b;
393                         case ExpressionType.Modulo:
394                                 return a % b;
395                         case ExpressionType.Power:
396                                 return System.Math.Pow (a, b);
397                         }
398
399                         throw new NotImplementedException ();
400
401                 }
402
403                 private static Int32 Evaluate (Int16 a, Int16 b, ExpressionType et)
404                 {
405                         switch (et) {
406                         case ExpressionType.Add:
407                                 return unchecked (a + b);
408                         case ExpressionType.AddChecked:
409                                 return checked (a + b);
410                         case ExpressionType.Subtract:
411                                 return unchecked (a - b);
412                         case ExpressionType.SubtractChecked:
413                                 return checked (a - b);
414                         case ExpressionType.Multiply:
415                                 return unchecked (a * b);
416                         case ExpressionType.MultiplyChecked:
417                                 return checked (a * b);
418                         case ExpressionType.Divide:
419                                 return a / b;
420                         case ExpressionType.Modulo:
421                                 return a % b;
422                         case ExpressionType.ExclusiveOr:
423                                 return a ^ b;
424                         case ExpressionType.And:
425                                 return a & b;
426                         case ExpressionType.Or:
427                                 return a | b;
428                         }
429
430                         throw new NotImplementedException ();
431                 }
432
433                 private static Int32 Evaluate (Int32 a, Int32 b, ExpressionType et)
434                 {
435                         switch (et) {
436                         case ExpressionType.Add:
437                                 return unchecked (a + b);
438                         case ExpressionType.AddChecked:
439                                 return checked (a + b);
440                         case ExpressionType.Subtract:
441                                 return unchecked (a - b);
442                         case ExpressionType.SubtractChecked:
443                                 return checked (a - b);
444                         case ExpressionType.Multiply:
445                                 return unchecked (a * b);
446                         case ExpressionType.MultiplyChecked:
447                                 return checked (a * b);
448                         case ExpressionType.Divide:
449                                 return a / b;
450                         case ExpressionType.Modulo:
451                                 return a % b;
452                         case ExpressionType.ExclusiveOr:
453                                 return a ^ b;
454                         case ExpressionType.And:
455                                 return a & b;
456                         case ExpressionType.Or:
457                                 return a | b;
458                         }
459
460                         throw new NotImplementedException ();
461                 }
462
463                 private static Int64 Evaluate (Int64 a, Int64 b, ExpressionType et)
464                 {
465                         switch (et) {
466                         case ExpressionType.Add:
467                                 return unchecked (a + b);
468                         case ExpressionType.AddChecked:
469                                 return checked (a + b);
470                         case ExpressionType.Subtract:
471                                 return unchecked (a - b);
472                         case ExpressionType.SubtractChecked:
473                                 return checked (a - b);
474                         case ExpressionType.Multiply:
475                                 return unchecked (a * b);
476                         case ExpressionType.MultiplyChecked:
477                                 return checked (a * b);
478                         case ExpressionType.Divide:
479                                 return a / b;
480                         case ExpressionType.Modulo:
481                                 return a % b;
482                         case ExpressionType.ExclusiveOr:
483                                 return a ^ b;
484                         case ExpressionType.And:
485                                 return a & b;
486                         case ExpressionType.Or:
487                                 return a | b;
488                         }
489
490                         throw new NotImplementedException ();
491                 }
492
493                 private static Int32 Evaluate (UInt16 a, UInt16 b, ExpressionType et)
494                 {
495                         switch (et) {
496                         case ExpressionType.Add:
497                                 return unchecked (a + b);
498                         case ExpressionType.AddChecked:
499                                 return checked (a + b);
500                         case ExpressionType.Subtract:
501                                 return unchecked (a - b);
502                         case ExpressionType.SubtractChecked:
503                                 return checked ((UInt16) (a - b));
504                         case ExpressionType.Multiply:
505                                 return unchecked (a * b);
506                         case ExpressionType.MultiplyChecked:
507                                 return checked (a * b);
508                         case ExpressionType.Divide:
509                                 return a / b;
510                         case ExpressionType.Modulo:
511                                 return a % b;
512                         case ExpressionType.ExclusiveOr:
513                                 return a ^ b;
514                         case ExpressionType.And:
515                                 return a & b;
516                         case ExpressionType.Or:
517                                 return a | b;
518                         }
519
520                         throw new NotImplementedException ();
521                 }
522
523                 private static UInt32 Evaluate (UInt32 a, UInt32 b, ExpressionType et)
524                 {
525                         switch (et) {
526                         case ExpressionType.Add:
527                                 return unchecked (a + b);
528                         case ExpressionType.AddChecked:
529                                 return checked (a + b);
530                         case ExpressionType.Subtract:
531                                 return unchecked (a - b);
532                         case ExpressionType.SubtractChecked:
533                                 return checked (a - b);
534                         case ExpressionType.Multiply:
535                                 return unchecked (a * b);
536                         case ExpressionType.MultiplyChecked:
537                                 return checked (a * b);
538                         case ExpressionType.Divide:
539                                 return a / b;
540                         case ExpressionType.Modulo:
541                                 return a % b;
542                         case ExpressionType.ExclusiveOr:
543                                 return a ^ b;
544                         case ExpressionType.And:
545                                 return a & b;
546                         case ExpressionType.Or:
547                                 return a | b;
548                         }
549
550                         throw new NotImplementedException ();
551                 }
552
553                 private static UInt64 Evaluate (UInt64 a, UInt64 b, ExpressionType et)
554                 {
555                         switch (et) {
556                         case ExpressionType.Add:
557                                 return unchecked (a + b);
558                         case ExpressionType.AddChecked:
559                                 return checked (a + b);
560                         case ExpressionType.Subtract:
561                                 return unchecked (a - b);
562                         case ExpressionType.SubtractChecked:
563                                 return checked (a - b);
564                         case ExpressionType.Multiply:
565                                 return unchecked (a * b);
566                         case ExpressionType.MultiplyChecked:
567                                 return checked (a * b);
568                         case ExpressionType.Divide:
569                                 return a / b;
570                         case ExpressionType.Modulo:
571                                 return a % b;
572                         case ExpressionType.ExclusiveOr:
573                                 return a ^ b;
574                         case ExpressionType.And:
575                                 return a & b;
576                         case ExpressionType.Or:
577                                 return a | b;
578                         }
579
580                         throw new NotImplementedException ();
581                 }
582
583                 private static object Evaluate (Char a, Char b, ExpressionType et)
584                 {
585                         switch (et) {
586                         case ExpressionType.ExclusiveOr:
587                                 return a ^ b;
588                         case ExpressionType.And:
589                                 return a & b;
590                         case ExpressionType.Or:
591                                 return a | b;
592                         }
593
594                         throw new NotImplementedException ();
595                 }
596
597                 private static Int32 Evaluate (SByte a, SByte b, ExpressionType et)
598                 {
599                         switch (et) {
600                         case ExpressionType.Add:
601                                 return unchecked (a + b);
602                         case ExpressionType.AddChecked:
603                                 return checked (a + b);
604                         case ExpressionType.Subtract:
605                                 return unchecked (a - b);
606                         case ExpressionType.SubtractChecked:
607                                 return checked (a - b);
608                         case ExpressionType.Multiply:
609                                 return unchecked (a * b);
610                         case ExpressionType.MultiplyChecked:
611                                 return checked (a * b);
612                         case ExpressionType.Divide:
613                                 return a / b;
614                         case ExpressionType.Modulo:
615                                 return a % b;
616                         case ExpressionType.ExclusiveOr:
617                                 return a ^ b;
618                         case ExpressionType.And:
619                                 return a & b;
620                         case ExpressionType.Or:
621                                 return a | b;
622                         }
623
624                         throw new NotImplementedException ();
625                 }
626
627                 private static Int32 Evaluate (Byte a, Byte b, ExpressionType et)
628                 {
629                         switch (et) {
630                         case ExpressionType.Add:
631                                 return unchecked (a + b);
632                         case ExpressionType.AddChecked:
633                                 return checked (a + b);
634                         case ExpressionType.Subtract:
635                                 return unchecked (a - b);
636                         case ExpressionType.SubtractChecked:
637                                 return checked (a - b);
638                         case ExpressionType.Multiply:
639                                 return unchecked (a * b);
640                         case ExpressionType.MultiplyChecked:
641                                 return checked (a * b);
642                         case ExpressionType.Divide:
643                                 return a / b;
644                         case ExpressionType.Modulo:
645                                 return a % b;
646                         case ExpressionType.ExclusiveOr:
647                                 return a ^ b;
648                         case ExpressionType.And:
649                                 return a & b;
650                         case ExpressionType.Or:
651                                 return a | b;
652                         }
653
654                         throw new NotImplementedException ();
655                 }
656
657                 private static Single Evaluate (Single a, Single b, ExpressionType et)
658                 {
659                         switch (et) {
660                         case ExpressionType.Add:
661                                 return unchecked (a + b);
662                         case ExpressionType.AddChecked:
663                                 return checked (a + b);
664                         case ExpressionType.Subtract:
665                                 return unchecked (a - b);
666                         case ExpressionType.SubtractChecked:
667                                 return checked (a - b);
668                         case ExpressionType.Multiply:
669                                 return unchecked (a * b);
670                         case ExpressionType.MultiplyChecked:
671                                 return checked (a * b);
672                         case ExpressionType.Divide:
673                                 return a / b;
674                         case ExpressionType.Modulo:
675                                 return a % b;
676                         }
677
678                         throw new NotImplementedException ();
679                 }
680
681                 private static bool Evaluate (bool a, bool b, ExpressionType et)
682                 {
683                         switch (et) {
684                         case ExpressionType.ExclusiveOr:
685                                 return a ^ b;
686                         case ExpressionType.And:
687                                 return a & b;
688                         case ExpressionType.Or:
689                                 return a | b;
690                         }
691
692                         throw new NotImplementedException ();
693                 }
694         }
695 }