Data Types C#

#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
{
    /// 
    /// Various utility methods relating to numbers.
    /// 

    /// 
    /// 


    /// Mainly for internal use within the framework.
    /// 


    /// 

    /// Aleksandar Seovic
    public sealed class NumberUtils
    {
        /// 
        /// Determines whether the supplied  is an integer.
        /// 

        /// The object to check.
        /// 
        ///  if the supplied  is an integer.
        /// 

        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);
        }
        /// 
        /// Determines whether the supplied  is a decimal number.
        /// 

        /// The object to check.
        /// 
        ///  if the supplied  is a decimal number.
        /// 

        public static bool IsDecimal(object number)
        {
            return (number is Single || number is Double || number is Decimal);
        }
        /// 
        /// Determines whether the supplied  is of numeric type.
        /// 

        /// The object to check.
        /// 
        ///   true if the specified object is of numeric type; otherwise, false.
        /// 

        public static bool IsNumber(object number)
        {
            return (IsInteger(number) || IsDecimal(number));
        }
        /// 
        /// Determines whether the supplied  can be converted to an integer.
        /// 

        /// The object to check.
        /// 
        ///  if the supplied  can be converted to an integer.
        /// 

        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))
                   );
        }
        /// 
        /// Determines whether the supplied  can be converted to an integer.
        /// 

        /// The object to check.
        /// 
        ///  if the supplied  can be converted to an integer.
        /// 

        public static bool CanConvertToDecimal(object number)
        {
            TypeConverter converter = TypeDescriptor.GetConverter(number);
            return (converter.CanConvertTo(typeof(Single))
                || converter.CanConvertTo(typeof(Double))
                || converter.CanConvertTo(typeof(Decimal))
                   );
        }
        /// 
        /// Determines whether the supplied  can be converted to a number.
        /// 

        /// The object to check.
        /// 
        ///   true if the specified object is decimal number; otherwise, false.
        /// 

        public static bool CanConvertToNumber(object number)
        {
            return (CanConvertToInteger(number) || CanConvertToDecimal(number));
        }
        /// 
        /// Is the supplied  equal to zero (0)?
        /// 

        /// The number to check.
        /// 
        ///  id the supplied  is equal to zero (0).
        /// 

        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;
        }
        /// 
        /// Negates the supplied .
        /// 

        /// The number to negate.
        /// The supplied  negated.
        /// 
        /// If the supplied  is not a supported numeric type.
        /// 
        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));
            }
        }
        /// 
        /// Returns the bitwise not (~) of the supplied .
        /// 

        /// The number.
        /// The value of ~.
        /// 
        /// If the supplied  is not a supported numeric type.
        /// 
        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));
            }
        }
        /// 
        /// Bitwise ANDs (&) the specified integral values.
        /// 

        /// The first number.
        /// The second number.
        /// 
        /// If one of the supplied arguments is not a supported integral types.
        /// 
        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));
            }
        }
        /// 
        /// Bitwise ORs (|) the specified integral values.
        /// 

        /// The first number.
        /// The second number.
        /// 
        /// If one of the supplied arguments is not a supported integral types.
        /// 
        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));
        }
        /// 
        /// Bitwise XORs (^) the specified integral values.
        /// 

        /// The first number.
        /// The second number.
        /// 
        /// If one of the supplied arguments is not a supported integral types.
        /// 
        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));
            }
        }
        /// 
        /// Adds the specified numbers.
        /// 

        /// The first number.
        /// The second number.
        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));
            }
        }
        /// 
        /// Subtracts the specified numbers.
        /// 

        /// The first number.
        /// The second number.
        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));
            }
        }
        /// 
        /// Multiplies the specified numbers.
        /// 

        /// The first number.
        /// The second number.
        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));
            }
        }
        /// 
        /// Divides the specified numbers.
        /// 

        /// The first number.
        /// The second number.
        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));
            }
        }
        /// 
        /// Calculates remainder for the specified numbers.
        /// 

        /// The first number (dividend).
        /// The second number (divisor).
        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));
            }
        }
        /// 
        /// Raises first number to the power of the second one.
        /// 

        /// The first number.
        /// The second number.
        public static object Power(object m, object n)
        {
            return Math.Pow(Convert.ToDouble(m), Convert.ToDouble(n));
        }
        /// 
        /// Coerces the types so they can be compared.
        /// 

        /// The right.
        /// The left.
        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
        /// 
        /// Creates a new instance of the  class.
        /// 

        /// 
        /// 


        /// This is a utility class, and as such exposes no public constructors.
        /// 


        /// 

        private NumberUtils()
        {
        }
        // CLOVER:ON
        #endregion
    }
}