#region License /* * Copyright 2002-2005 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #endregion #region Imports using System; using System.ComponentModel; #endregion namespace Spring.Util { /// <summary> /// Various utility methods relating to numbers. /// </summary> /// <remarks> /// <p> /// Mainly for internal use within the framework. /// </p> /// </remarks> /// <author>Aleksandar Seovic</author> public sealed class NumberUtils { /// <summary> /// Determines whether the supplied <paramref name="number"/> is an integer. /// </summary> /// <param name="number">The object to check.</param> /// <returns> /// <see lang="true"/> if the supplied <paramref name="number"/> is an integer. /// </returns> public static bool IsInteger(object number) { return (number is Int32 || number is Int16 || number is Int64 || number is UInt32 || number is UInt16 || number is UInt64 || number is Byte || number is SByte); } /// <summary> /// Determines whether the supplied <paramref name="number"/> is a decimal number. /// </summary> /// <param name="number">The object to check.</param> /// <returns> /// <see lang="true"/> if the supplied <paramref name="number"/> is a decimal number. /// </returns> public static bool IsDecimal(object number) { return (number is Single || number is Double || number is Decimal); } /// <summary> /// Determines whether the supplied <paramref name="number"/> is of numeric type. /// </summary> /// <param name="number">The object to check.</param> /// <returns> /// <c>true</c> if the specified object is of numeric type; otherwise, <c>false</c>. /// </returns> public static bool IsNumber(object number) { return (IsInteger(number) || IsDecimal(number)); } /// <summary> /// Determines whether the supplied <paramref name="number"/> can be converted to an integer. /// </summary> /// <param name="number">The object to check.</param> /// <returns> /// <see lang="true"/> if the supplied <paramref name="number"/> can be converted to an integer. /// </returns> public static bool CanConvertToInteger(object number) { TypeConverter converter = TypeDescriptor.GetConverter(number); return (converter.CanConvertTo(typeof(Int32)) || converter.CanConvertTo(typeof(Int16)) || converter.CanConvertTo(typeof(Int64)) || converter.CanConvertTo(typeof(UInt16)) || converter.CanConvertTo(typeof(UInt64)) || converter.CanConvertTo(typeof(Byte)) || converter.CanConvertTo(typeof(SByte)) ); } /// <summary> /// Determines whether the supplied <paramref name="number"/> can be converted to an integer. /// </summary> /// <param name="number">The object to check.</param> /// <returns> /// <see lang="true"/> if the supplied <paramref name="number"/> can be converted to an integer. /// </returns> public static bool CanConvertToDecimal(object number) { TypeConverter converter = TypeDescriptor.GetConverter(number); return (converter.CanConvertTo(typeof(Single)) || converter.CanConvertTo(typeof(Double)) || converter.CanConvertTo(typeof(Decimal)) ); } /// <summary> /// Determines whether the supplied <paramref name="number"/> can be converted to a number. /// </summary> /// <param name="number">The object to check.</param> /// <returns> /// <c>true</c> if the specified object is decimal number; otherwise, <c>false</c>. /// </returns> public static bool CanConvertToNumber(object number) { return (CanConvertToInteger(number) || CanConvertToDecimal(number)); } /// <summary> /// Is the supplied <paramref name="number"/> equal to zero (0)? /// </summary> /// <param name="number">The number to check.</param> /// <returns> /// <see lang="true"/> id the supplied <paramref name="number"/> is equal to zero (0). /// </returns> public static bool IsZero(object number) { if (number is Int32) return ((Int32)number) == 0; else if (number is Int16) return ((Int16)number) == 0; else if (number is Int64) return ((Int64)number) == 0; else if (number is UInt16) return ((Int32)number) == 0; else if (number is UInt32) return ((Int64)number) == 0; else if (number is UInt64) return (Convert.ToDecimal(number) == 0); else if (number is Byte) return ((Int16)number) == 0; else if (number is SByte) return ((Int16)number) == 0; else if (number is Single) return ((Single)number) == 0f; else if (number is Double) return ((Double)number) == 0d; else if (number is Decimal) return ((Decimal)number) == 0m; return false; } /// <summary> /// Negates the supplied <paramref name="number"/>. /// </summary> /// <param name="number">The number to negate.</param> /// <returns>The supplied <paramref name="number"/> negated.</returns> /// <exception cref="System.ArgumentException"> /// If the supplied <paramref name="number"/> is not a supported numeric type. /// </exception> public static object Negate(object number) { if (number is Int32) return -((Int32)number); else if (number is Int16) return -((Int16)number); else if (number is Int64) return -((Int64)number); else if (number is UInt16) return -((Int32)number); else if (number is UInt32) return -((Int64)number); else if (number is UInt64) return -(Convert.ToDecimal(number)); else if (number is Byte) return -((Int16)number); else if (number is SByte) return -((Int16)number); else if (number is Single) return -((Single)number); else if (number is Double) return -((Double)number); else if (number is Decimal) return -((Decimal)number); else { throw new ArgumentException(string.Format("'{0}' is not one of the supported numeric types.", number)); } } /// <summary> /// Returns the bitwise not (~) of the supplied <paramref name="number"/>. /// </summary> /// <param name="number">The number.</param> /// <returns>The value of ~<paramref name="number"/>.</returns> /// <exception cref="System.ArgumentException"> /// If the supplied <paramref name="number"/> is not a supported numeric type. /// </exception> public static object BitwiseNot(object number) { if (number is bool) return !((bool)number); else if (number is Int32) return ~((Int32)number); else if (number is Int16) return ~((Int16)number); else if (number is Int64) return ~((Int64)number); else if (number is UInt16) return ~((UInt16)number); else if (number is UInt32) return ~((UInt32)number); else if (number is UInt64) return ~((UInt64)number); else if (number is Byte) return ~((Byte)number); else if (number is SByte) return ~((SByte)number); else { throw new ArgumentException(string.Format("'{0}' is not one of the supported integer types.", number)); } } /// <summary> /// Bitwise ANDs (&amp;) the specified integral values. /// </summary> /// <param name="m">The first number.</param> /// <param name="n">The second number.</param> /// <exception cref="System.ArgumentException"> /// If one of the supplied arguments is not a supported integral types. /// </exception> public static object BitwiseAnd(object m, object n) { CoerceTypes(ref m, ref n); if (n is bool) return (bool)m & (bool)n; else if (n is Int32) return (Int32)m & (Int32)n; else if (n is Int16) return (Int16)m & (Int16)n; else if (n is Int64) return (Int64)m & (Int64)n; else if (n is UInt16) return (UInt16)m & (UInt16)n; else if (n is UInt32) return (UInt32)m & (UInt32)n; else if (n is UInt64) return (UInt64)m & (UInt64)n; else if (n is Byte) return (Byte)m & (Byte)n; else if (n is SByte) return (SByte)m & (SByte)n; else { throw new ArgumentException(string.Format("'{0}' and/or '{1}' are not one of the supported integral types.", m, n)); } } /// <summary> /// Bitwise ORs (|) the specified integral values. /// </summary> /// <param name="m">The first number.</param> /// <param name="n">The second number.</param> /// <exception cref="System.ArgumentException"> /// If one of the supplied arguments is not a supported integral types. /// </exception> public static object BitwiseOr(object m, object n) { CoerceTypes(ref m, ref n); if (n is bool) return (bool)m | (bool)n; else if (n is Int32) return (Int32)m | (Int32)n; #if NET_2_0 else if (n is Int16) return (Int16)m | (Int16)n; #endif else if (n is Int64) return (Int64)m | (Int64)n; else if (n is UInt16) return (UInt16)m | (UInt16)n; else if (n is UInt32) return (UInt32)m | (UInt32)n; else if (n is UInt64) return (UInt64)m | (UInt64)n; else if (n is Byte) return (Byte)m | (Byte)n; #if NET_2_0 else if (n is SByte) { if (SystemUtils.MonoRuntime) { SByte x = (sbyte) n; SByte y = (sbyte) m; int result = (int) x | (int) y; return SByte.Parse(result.ToString()); } return (SByte) ((SByte) m | (SByte) n); } #endif throw new ArgumentException(string.Format("'{0}' and/or '{1}' are not one of the supported integral types.", m, n)); } /// <summary> /// Bitwise XORs (^) the specified integral values. /// </summary> /// <param name="m">The first number.</param> /// <param name="n">The second number.</param> /// <exception cref="System.ArgumentException"> /// If one of the supplied arguments is not a supported integral types. /// </exception> public static object BitwiseXor(object m, object n) { CoerceTypes(ref m, ref n); if (n is bool) return (bool)m ^ (bool)n; else if (n is Int32) return (Int32)m ^ (Int32)n; else if (n is Int16) return (Int16)m ^ (Int16)n; else if (n is Int64) return (Int64)m ^ (Int64)n; else if (n is UInt16) return (UInt16)m ^ (UInt16)n; else if (n is UInt32) return (UInt32)m ^ (UInt32)n; else if (n is UInt64) return (UInt64)m ^ (UInt64)n; else if (n is Byte) return (Byte)m ^ (Byte)n; else if (n is SByte) return (SByte)m ^ (SByte)n; else { throw new ArgumentException(string.Format("'{0}' and/or '{1}' are not one of the supported integral types.", m, n)); } } /// <summary> /// Adds the specified numbers. /// </summary> /// <param name="m">The first number.</param> /// <param name="n">The second number.</param> public static object Add(object m, object n) { CoerceTypes(ref m, ref n); if (n is Int32) return (Int32)m + (Int32)n; else if (n is Int16) return (Int16)m + (Int16)n; else if (n is Int64) return (Int64)m + (Int64)n; else if (n is UInt16) return (UInt16)m + (UInt16)n; else if (n is UInt32) return (UInt32)m + (UInt32)n; else if (n is UInt64) return (UInt64)m + (UInt64)n; else if (n is Byte) return (Byte)m + (Byte)n; else if (n is SByte) return (SByte)m + (SByte)n; else if (n is Single) return (Single)m + (Single)n; else if (n is Double) return (Double)m + (Double)n; else if (n is Decimal) return (Decimal)m + (Decimal)n; else { throw new ArgumentException(string.Format("'{0}' and/or '{1}' are not one of the supported numeric types.", m, n)); } } /// <summary> /// Subtracts the specified numbers. /// </summary> /// <param name="m">The first number.</param> /// <param name="n">The second number.</param> public static object Subtract(object m, object n) { CoerceTypes(ref m, ref n); if (n is Int32) return (Int32)m - (Int32)n; else if (n is Int16) return (Int16)m - (Int16)n; else if (n is Int64) return (Int64)m - (Int64)n; else if (n is UInt16) return (UInt16)m - (UInt16)n; else if (n is UInt32) return (UInt32)m - (UInt32)n; else if (n is UInt64) return (UInt64)m - (UInt64)n; else if (n is Byte) return (Byte)m - (Byte)n; else if (n is SByte) return (SByte)m - (SByte)n; else if (n is Single) return (Single)m - (Single)n; else if (n is Double) return (Double)m - (Double)n; else if (n is Decimal) return (Decimal)m - (Decimal)n; else { throw new ArgumentException(string.Format("'{0}' and/or '{1}' are not one of the supported numeric types.", m, n)); } } /// <summary> /// Multiplies the specified numbers. /// </summary> /// <param name="m">The first number.</param> /// <param name="n">The second number.</param> public static object Multiply(object m, object n) { CoerceTypes(ref m, ref n); if (n is Int32) return (Int32)m * (Int32)n; else if (n is Int16) return (Int16)m * (Int16)n; else if (n is Int64) return (Int64)m * (Int64)n; else if (n is UInt16) return (UInt16)m * (UInt16)n; else if (n is UInt32) return (UInt32)m * (UInt32)n; else if (n is UInt64) return (UInt64)m * (UInt64)n; else if (n is Byte) return (Byte)m * (Byte)n; else if (n is SByte) return (SByte)m * (SByte)n; else if (n is Single) return (Single)m * (Single)n; else if (n is Double) return (Double)m * (Double)n; else if (n is Decimal) return (Decimal)m * (Decimal)n; else { throw new ArgumentException(string.Format("'{0}' and/or '{1}' are not one of the supported numeric types.", m, n)); } } /// <summary> /// Divides the specified numbers. /// </summary> /// <param name="m">The first number.</param> /// <param name="n">The second number.</param> public static object Divide(object m, object n) { CoerceTypes(ref m, ref n); if (n is Int32) return (Int32)m / (Int32)n; else if (n is Int16) return (Int16)m / (Int16)n; else if (n is Int64) return (Int64)m / (Int64)n; else if (n is UInt16) return (UInt16)m / (UInt16)n; else if (n is UInt32) return (UInt32)m / (UInt32)n; else if (n is UInt64) return (UInt64)m / (UInt64)n; else if (n is Byte) return (Byte)m / (Byte)n; else if (n is SByte) return (SByte)m / (SByte)n; else if (n is Single) return (Single)m / (Single)n; else if (n is Double) return (Double)m / (Double)n; else if (n is Decimal) return (Decimal)m / (Decimal)n; else { throw new ArgumentException(string.Format("'{0}' and/or '{1}' are not one of the supported numeric types.", m, n)); } } /// <summary> /// Calculates remainder for the specified numbers. /// </summary> /// <param name="m">The first number (dividend).</param> /// <param name="n">The second number (divisor).</param> public static object Modulus(object m, object n) { CoerceTypes(ref m, ref n); if (n is Int32) return (Int32)m % (Int32)n; else if (n is Int16) return (Int16)m % (Int16)n; else if (n is Int64) return (Int64)m % (Int64)n; else if (n is UInt16) return (UInt16)m % (UInt16)n; else if (n is UInt32) return (UInt32)m % (UInt32)n; else if (n is UInt64) return (UInt64)m % (UInt64)n; else if (n is Byte) return (Byte)m % (Byte)n; else if (n is SByte) return (SByte)m % (SByte)n; else if (n is Single) return (Single)m % (Single)n; else if (n is Double) return (Double)m % (Double)n; else if (n is Decimal) return (Decimal)m % (Decimal)n; else { throw new ArgumentException(string.Format("'{0}' and/or '{1}' are not one of the supported numeric types.", m, n)); } } /// <summary> /// Raises first number to the power of the second one. /// </summary> /// <param name="m">The first number.</param> /// <param name="n">The second number.</param> public static object Power(object m, object n) { return Math.Pow(Convert.ToDouble(m), Convert.ToDouble(n)); } /// <summary> /// Coerces the types so they can be compared. /// </summary> /// <param name="m">The right.</param> /// <param name="n">The left.</param> public static void CoerceTypes(ref object m, ref object n) { TypeCode leftTypeCode = Convert.GetTypeCode(m); TypeCode rightTypeCode = Convert.GetTypeCode(n); if (leftTypeCode > rightTypeCode) { n = Convert.ChangeType(n, leftTypeCode); } else { m = Convert.ChangeType(m, rightTypeCode); } } #region Constructor (s) / Destructor // CLOVER:OFF /// <summary> /// Creates a new instance of the <see cref="Spring.Util.NumberUtils"/> class. /// </summary> /// <remarks> /// <p> /// This is a utility class, and as such exposes no public constructors. /// </p> /// </remarks> private NumberUtils() { } // CLOVER:ON #endregion } }