// // Math.cs // // (C) 2008 Mainsoft, Inc. (http://www.mainsoft.com) // (C) 2008 db4objects, Inc. (http://www.db4o.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Globalization; using System.Linq.Expressions; namespace System.Linq.jvm { class Math { public static object Evaluate (object a, object b, Type t, ExpressionType et) { TypeCode tc = Type.GetTypeCode (t); if (tc == TypeCode.Object) { if (!t.IsNullable ()) { throw new NotImplementedException ( string.Format ( "Expression with Node type {0} for type {1}", t.FullName, tc)); } return EvaluateNullable (a, b, Type.GetTypeCode (t.GetGenericArguments () [0]), et); } return Evaluate (a, b, tc, et); } public static object EvaluateNullable (object a, object b, TypeCode tc, ExpressionType et) { object o = null; if (a == null || b == null) { if (tc != TypeCode.Boolean) { return null; } switch (et) { case ExpressionType.And: o = And (a, b); break; case ExpressionType.Or: o = Or (a, b); break; case ExpressionType.ExclusiveOr: o = ExclusiveOr (a, b); break; } } else { o = Evaluate (a, b, tc, et); } return Convert2Nullable (o, tc); } private static object ExclusiveOr (object a, object b) { if (a == null || b == null) { return null; } return (bool) a ^ (bool) b; } public static object Or (object a, object b) { if (a == null) { if (b == null || !((bool) b)) { return null; } return true; } if (b == null) { if (a == null || !((bool) a)) { return null; } return true; } return (bool) a || (bool) b; } public static object And (object a, object b) { if (a == null) { if (b == null || (bool) b) { return null; } return false; } if (b == null) { if (a == null || (bool) a) { return null; } return false; } return (bool) a && (bool) b; } private static object Convert2Nullable (object o, TypeCode tc) { if (o == null) { return null; } switch (tc) { case TypeCode.Char: return new Nullable ((Char) o); case TypeCode.Byte: return new Nullable ((Byte) o); case TypeCode.Decimal: return new Nullable ((Decimal) o); case TypeCode.Double: return new Nullable ((Double) o); case TypeCode.Int16: return new Nullable ((Int16) o); case TypeCode.Int32: return new Nullable ((Int32) o); case TypeCode.Int64: return new Nullable ((Int64) o); case TypeCode.UInt16: return new Nullable ((UInt16) o); case TypeCode.UInt32: return new Nullable ((UInt32) o); case TypeCode.SByte: return new Nullable ((SByte) o); case TypeCode.Single: return new Nullable ((Single) o); case TypeCode.Boolean: return new Nullable ((Boolean) o); } throw new NotImplementedException (); } public static object Evaluate (object a, object b, TypeCode tc, ExpressionType et) { switch (tc) { case TypeCode.Boolean: return Evaluate (Convert.ToBoolean (a), Convert.ToBoolean (b), et); case TypeCode.Char: return Evaluate (Convert.ToChar (a), Convert.ToChar (b), et); case TypeCode.Byte: return unchecked ((Byte) Evaluate (Convert.ToByte (a), Convert.ToByte (b), et)); case TypeCode.Decimal: return Evaluate (Convert.ToDecimal (a), Convert.ToDecimal (b), et); case TypeCode.Double: return Evaluate (Convert.ToDouble (a), Convert.ToDouble (b), et); case TypeCode.Int16: return unchecked ((Int16) Evaluate (Convert.ToInt16 (a), Convert.ToInt16 (b), et)); case TypeCode.Int32: return Evaluate (Convert.ToInt32 (a), Convert.ToInt32 (b), et); case TypeCode.Int64: return Evaluate (Convert.ToInt64 (a), Convert.ToInt64 (b), et); case TypeCode.UInt16: return unchecked ((UInt16) Evaluate (Convert.ToUInt16 (a), Convert.ToUInt16 (b), et)); case TypeCode.UInt32: return Evaluate (Convert.ToUInt32 (a), Convert.ToUInt32 (b), et); case TypeCode.UInt64: return Evaluate (Convert.ToUInt64 (a), Convert.ToUInt64 (b), et); case TypeCode.SByte: return unchecked ((SByte) Evaluate (Convert.ToSByte (a), Convert.ToSByte (b), et)); case TypeCode.Single: return Evaluate (Convert.ToSingle (a), Convert.ToSingle (b), et); } throw new NotImplementedException (); } public static object NegateChecked (object a, TypeCode tc) { switch (tc) { case TypeCode.Char: return checked (-Convert.ToChar (a)); case TypeCode.Byte: return checked (-Convert.ToByte (a)); case TypeCode.Decimal: return checked (-Convert.ToDecimal (a)); case TypeCode.Double: return checked (-Convert.ToDouble (a)); case TypeCode.Int16: return checked (-Convert.ToInt16 (a)); case TypeCode.Int32: return checked (-Convert.ToInt32 (a)); case TypeCode.Int64: return checked (-Convert.ToInt64 (a)); case TypeCode.UInt16: return checked (-Convert.ToUInt16 (a)); case TypeCode.UInt32: return checked (-Convert.ToUInt32 (a)); case TypeCode.SByte: return checked (-Convert.ToSByte (a)); case TypeCode.Single: return checked (-Convert.ToSingle (a)); } throw new NotImplementedException (); } static object CreateInstance (Type type, params object [] arguments) { return type.GetConstructor ( (from argument in arguments select argument.GetType ()).ToArray ()).Invoke (arguments); } public static object ConvertToTypeChecked (object a, Type fromType, Type toType) { if (toType.IsNullable ()) return a == null ? a : CreateInstance (toType, ConvertToTypeChecked (a, fromType.GetNotNullableType (), toType.GetNotNullableType ())); if (a == null) { if (!toType.IsValueType) return a; if (fromType.IsNullable ()) throw new InvalidOperationException ("Nullable object must have a value"); } if (IsType (toType, a)) { return a; } if (Expression.IsPrimitiveConversion (fromType, toType)) return Convert.ChangeType (a, toType, CultureInfo.CurrentCulture); throw new NotImplementedException ( string.Format ("No Convert defined for type {0} ", toType)); } public static object ConvertToTypeUnchecked (object a, Type fromType, Type toType) { if (toType.IsNullable ()) return a == null ? a : CreateInstance (toType, ConvertToTypeUnchecked (a, fromType.GetNotNullableType (), toType.GetNotNullableType ())); if (a == null) { if (!toType.IsValueType) return a; if (fromType.IsNullable ()) throw new InvalidOperationException ("Nullable object must have a value"); } if (IsType (toType, a)) return a; if (Expression.IsPrimitiveConversion (fromType, toType)) return Conversion.ConvertPrimitiveUnChecked (fromType, toType, a); throw new NotImplementedException ( string.Format ("No Convert defined for type {0} ", toType)); } public static bool IsType (Type t, Object o) { return t.IsInstanceOfType (o); } public static object Negate (object a, TypeCode tc) { switch (tc) { case TypeCode.Char: return unchecked (-Convert.ToChar (a)); case TypeCode.Byte: return unchecked (-Convert.ToByte (a)); case TypeCode.Decimal: return unchecked (-Convert.ToDecimal (a)); case TypeCode.Double: return unchecked (-Convert.ToDouble (a)); case TypeCode.Int16: return unchecked (-Convert.ToInt16 (a)); case TypeCode.Int32: return unchecked (-Convert.ToInt32 (a)); case TypeCode.Int64: return unchecked (-Convert.ToInt64 (a)); case TypeCode.UInt16: return unchecked (-Convert.ToUInt16 (a)); case TypeCode.UInt32: return unchecked (-Convert.ToUInt32 (a)); case TypeCode.SByte: return unchecked (-Convert.ToSByte (a)); case TypeCode.Single: return unchecked (-Convert.ToSingle (a)); } throw new NotImplementedException (); } public static object RightShift (object a, int n, TypeCode tc) { switch (tc) { case TypeCode.Int16: return Convert.ToInt16 (a) >> n; case TypeCode.Int32: return Convert.ToInt32 (a) >> n; case TypeCode.Int64: return Convert.ToInt64 (a) >> n; case TypeCode.UInt16: return Convert.ToUInt16 (a) >> n; case TypeCode.UInt32: return Convert.ToUInt32 (a) >> n; case TypeCode.UInt64: return Convert.ToUInt64 (a) >> n; } throw new NotImplementedException (); } public static object LeftShift (object a, int n, TypeCode tc) { switch (tc) { case TypeCode.Int16: return Convert.ToInt16 (a) << n; case TypeCode.Int32: return Convert.ToInt32 (a) << n; case TypeCode.Int64: return Convert.ToInt64 (a) << n; case TypeCode.UInt16: return Convert.ToUInt16 (a) << n; case TypeCode.UInt32: return Convert.ToUInt32 (a) << n; case TypeCode.UInt64: return Convert.ToUInt64 (a) << n; } throw new NotImplementedException (); } private static Decimal Evaluate (Decimal a, Decimal b, ExpressionType et) { switch (et) { case ExpressionType.Add: return unchecked (a + b); case ExpressionType.AddChecked: return checked (a + b); case ExpressionType.Subtract: return unchecked (a - b); case ExpressionType.SubtractChecked: return checked (a - b); case ExpressionType.Multiply: return unchecked (a * b); case ExpressionType.MultiplyChecked: return checked (a * b); case ExpressionType.Divide: return a / b; case ExpressionType.Modulo: return a % b; } throw new NotImplementedException (); } private static Double Evaluate (Double a, Double b, ExpressionType et) { switch (et) { case ExpressionType.Add: return unchecked (a + b); case ExpressionType.AddChecked: return checked (a + b); case ExpressionType.Subtract: return unchecked (a - b); case ExpressionType.SubtractChecked: return checked (a - b); case ExpressionType.Multiply: return unchecked (a * b); case ExpressionType.MultiplyChecked: return checked (a * b); case ExpressionType.Divide: return a / b; case ExpressionType.Modulo: return a % b; case ExpressionType.Power: return System.Math.Pow (a, b); } throw new NotImplementedException (); } private static Int32 Evaluate (Int16 a, Int16 b, ExpressionType et) { switch (et) { case ExpressionType.Add: return unchecked (a + b); case ExpressionType.AddChecked: return checked (a + b); case ExpressionType.Subtract: return unchecked (a - b); case ExpressionType.SubtractChecked: return checked (a - b); case ExpressionType.Multiply: return unchecked (a * b); case ExpressionType.MultiplyChecked: return checked (a * b); case ExpressionType.Divide: return a / b; case ExpressionType.Modulo: return a % b; case ExpressionType.ExclusiveOr: return a ^ b; case ExpressionType.And: return a & b; case ExpressionType.Or: return a | b; } throw new NotImplementedException (); } private static Int32 Evaluate (Int32 a, Int32 b, ExpressionType et) { switch (et) { case ExpressionType.Add: return unchecked (a + b); case ExpressionType.AddChecked: return checked (a + b); case ExpressionType.Subtract: return unchecked (a - b); case ExpressionType.SubtractChecked: return checked (a - b); case ExpressionType.Multiply: return unchecked (a * b); case ExpressionType.MultiplyChecked: return checked (a * b); case ExpressionType.Divide: return a / b; case ExpressionType.Modulo: return a % b; case ExpressionType.ExclusiveOr: return a ^ b; case ExpressionType.And: return a & b; case ExpressionType.Or: return a | b; } throw new NotImplementedException (); } private static Int64 Evaluate (Int64 a, Int64 b, ExpressionType et) { switch (et) { case ExpressionType.Add: return unchecked (a + b); case ExpressionType.AddChecked: return checked (a + b); case ExpressionType.Subtract: return unchecked (a - b); case ExpressionType.SubtractChecked: return checked (a - b); case ExpressionType.Multiply: return unchecked (a * b); case ExpressionType.MultiplyChecked: return checked (a * b); case ExpressionType.Divide: return a / b; case ExpressionType.Modulo: return a % b; case ExpressionType.ExclusiveOr: return a ^ b; case ExpressionType.And: return a & b; case ExpressionType.Or: return a | b; } throw new NotImplementedException (); } private static Int32 Evaluate (UInt16 a, UInt16 b, ExpressionType et) { switch (et) { case ExpressionType.Add: return unchecked (a + b); case ExpressionType.AddChecked: return checked (a + b); case ExpressionType.Subtract: return unchecked (a - b); case ExpressionType.SubtractChecked: return checked ((UInt16) (a - b)); case ExpressionType.Multiply: return unchecked (a * b); case ExpressionType.MultiplyChecked: return checked (a * b); case ExpressionType.Divide: return a / b; case ExpressionType.Modulo: return a % b; case ExpressionType.ExclusiveOr: return a ^ b; case ExpressionType.And: return a & b; case ExpressionType.Or: return a | b; } throw new NotImplementedException (); } private static UInt32 Evaluate (UInt32 a, UInt32 b, ExpressionType et) { switch (et) { case ExpressionType.Add: return unchecked (a + b); case ExpressionType.AddChecked: return checked (a + b); case ExpressionType.Subtract: return unchecked (a - b); case ExpressionType.SubtractChecked: return checked (a - b); case ExpressionType.Multiply: return unchecked (a * b); case ExpressionType.MultiplyChecked: return checked (a * b); case ExpressionType.Divide: return a / b; case ExpressionType.Modulo: return a % b; case ExpressionType.ExclusiveOr: return a ^ b; case ExpressionType.And: return a & b; case ExpressionType.Or: return a | b; } throw new NotImplementedException (); } private static UInt64 Evaluate (UInt64 a, UInt64 b, ExpressionType et) { switch (et) { case ExpressionType.Add: return unchecked (a + b); case ExpressionType.AddChecked: return checked (a + b); case ExpressionType.Subtract: return unchecked (a - b); case ExpressionType.SubtractChecked: return checked (a - b); case ExpressionType.Multiply: return unchecked (a * b); case ExpressionType.MultiplyChecked: return checked (a * b); case ExpressionType.Divide: return a / b; case ExpressionType.Modulo: return a % b; case ExpressionType.ExclusiveOr: return a ^ b; case ExpressionType.And: return a & b; case ExpressionType.Or: return a | b; } throw new NotImplementedException (); } private static object Evaluate (Char a, Char b, ExpressionType et) { switch (et) { case ExpressionType.ExclusiveOr: return a ^ b; case ExpressionType.And: return a & b; case ExpressionType.Or: return a | b; } throw new NotImplementedException (); } private static Int32 Evaluate (SByte a, SByte b, ExpressionType et) { switch (et) { case ExpressionType.Add: return unchecked (a + b); case ExpressionType.AddChecked: return checked (a + b); case ExpressionType.Subtract: return unchecked (a - b); case ExpressionType.SubtractChecked: return checked (a - b); case ExpressionType.Multiply: return unchecked (a * b); case ExpressionType.MultiplyChecked: return checked (a * b); case ExpressionType.Divide: return a / b; case ExpressionType.Modulo: return a % b; case ExpressionType.ExclusiveOr: return a ^ b; case ExpressionType.And: return a & b; case ExpressionType.Or: return a | b; } throw new NotImplementedException (); } private static Int32 Evaluate (Byte a, Byte b, ExpressionType et) { switch (et) { case ExpressionType.Add: return unchecked (a + b); case ExpressionType.AddChecked: return checked (a + b); case ExpressionType.Subtract: return unchecked (a - b); case ExpressionType.SubtractChecked: return checked (a - b); case ExpressionType.Multiply: return unchecked (a * b); case ExpressionType.MultiplyChecked: return checked (a * b); case ExpressionType.Divide: return a / b; case ExpressionType.Modulo: return a % b; case ExpressionType.ExclusiveOr: return a ^ b; case ExpressionType.And: return a & b; case ExpressionType.Or: return a | b; } throw new NotImplementedException (); } private static Single Evaluate (Single a, Single b, ExpressionType et) { switch (et) { case ExpressionType.Add: return unchecked (a + b); case ExpressionType.AddChecked: return checked (a + b); case ExpressionType.Subtract: return unchecked (a - b); case ExpressionType.SubtractChecked: return checked (a - b); case ExpressionType.Multiply: return unchecked (a * b); case ExpressionType.MultiplyChecked: return checked (a * b); case ExpressionType.Divide: return a / b; case ExpressionType.Modulo: return a % b; } throw new NotImplementedException (); } private static bool Evaluate (bool a, bool b, ExpressionType et) { switch (et) { case ExpressionType.ExclusiveOr: return a ^ b; case ExpressionType.And: return a & b; case ExpressionType.Or: return a | b; } throw new NotImplementedException (); } } }