Typo.
[NovacoinLibrary.git] / Novacoin / base_uint.cs
index c2daad5..8b36b12 100644 (file)
 
 
 using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
 
 namespace Novacoin
 {
-    public class base_uint : IComparable<base_uint>, IEquatable<base_uint>
+    /// <summary>
+    /// Base class for uint256 and uint160.
+    /// </summary>
+    public class base_uint : IComparable<base_uint>, IEquatable<base_uint>, IEqualityComparer<base_uint>
     {
+        #region Internal representation
+        /// <summary>
+        /// Length of internal representation
+        /// </summary>
         protected int nWidth;
+        /// <summary>
+        /// Big numbers are stored as array of unsigned 32-bit integers.
+        /// </summary>
         protected uint[] pn;
+        #endregion
 
-        public double getDouble()
-        {
-            double ret = 0.0;
-            double fact = 1.0;
-
-            for (int i = 0; i < nWidth; i++)
-            {
-                ret += fact * pn[i];
-                fact *= 4294967296.0;
-            }
-
-            return ret;
-        }
-
-        public ulong GetLow64()
-        {
-            return pn[0] | (ulong)pn[1] << 32;
-        }
-
-        public uint GetLow32()
-        {
-            return pn[0];
-        }
-
-        public int Size
+        #region Helper properties
+        public double Double
         {
             get
             {
-                return nWidth;
-            }
-        }
-
+                double ret = 0.0;
+                double fact = 1.0;
 
-        public static bool operator !(base_uint a)
-        {
-            for (int i = 0; i < a.nWidth; i++)
-            {
-                if (a.pn[i] != 0)
+                for (int i = 0; i < nWidth; i++)
                 {
-                    return false;
+                    ret += fact * pn[i];
+                    fact *= 4294967296.0;
                 }
-            }
-            return true;
-        }
 
-        public static base_uint operator ~(base_uint a)
-        {
-            var ret = new base_uint();
-            for (int i = 0; i < a.nWidth; i++)
-            {
-                ret.pn[i] = ~a.pn[i];
+                return ret;
             }
-            return ret;
         }
 
-        public static base_uint operator -(base_uint a)
+        public ulong Low64
         {
-            var ret = new base_uint();
-            for (int i = 0; i < a.nWidth; i++)
-            {
-                ret.pn[i] = ~a.pn[i];
-            }
-            ret++;
-            return ret;
+            get { return pn[0] | (ulong)pn[1] << 32; }
         }
 
-
-        public static base_uint operator ++(base_uint a)
+        public uint Low32
         {
-            int i = 0;
-            while (++a.pn[i] == 0 && i < a.nWidth - 1)
-            {
-                i++;
-            }
-            return a;
-        }
-
-        public static base_uint operator --(base_uint a)
-        {
-            int i = 0;
-            while (--a.pn[i] == uint.MaxValue && i < a.nWidth - 1)
-            {
-                i++;
-            }
-            return a;
+            get { return pn[0]; }
         }
 
-        public static base_uint operator ^(base_uint a, base_uint b)
+        /// <summary>
+        /// Total size in bytes.
+        /// </summary>
+        public int Size
         {
-            var result = new base_uint();
-            result.pn = new uint[a.nWidth];
-            for (int i = 0; i < result.nWidth; i++)
+            get
             {
-                result.pn[i] = a.pn[i] ^ b.pn[i];
+                return nWidth * sizeof(uint);
             }
-            return result;
         }
 
-        public static base_uint operator +(base_uint a, base_uint b)
+        /// <summary>
+        /// Zero or the position of highest non-zero bit plus one.
+        /// </summary>
+        protected int bits
         {
-            var result = new base_uint();
-            ulong carry = 0;
-            for (int i = 0; i < result.nWidth; i++)
+            get
             {
-                ulong n = carry + a.pn[i] + b.pn[i];
-                result.pn[i] = (uint)(n & 0xffffffff);
-                carry = n >> 32;
+                for (int pos = nWidth - 1; pos >= 0; pos--)
+                {
+                    if (pn[pos] != 0)
+                    {
+                        for (int bits = 31; bits > 0; bits--)
+                        {
+                            if ((pn[pos] & 1 << bits) != 0)
+                                return 32 * pos + bits + 1;
+                        }
+                        return 32 * pos + 1;
+                    }
+                }
+                return 0;
             }
-            return result;
         }
+        #endregion
 
-        public static base_uint operator -(base_uint a, base_uint b)
-        {
-            return a + (-b);
-        }
 
-        public static base_uint operator &(base_uint a, base_uint b)
+        /// <summary>
+        /// Negation operator
+        /// </summary>
+        /// <param name="a">Value</param>
+        /// <returns>True if value is zero, false otherwise.</returns>
+        public static bool operator !(base_uint a)
         {
-            var result = new base_uint();
-            result.pn = new uint[a.nWidth];
-            for (int i = 0; i < result.nWidth; i++)
+            for (int i = 0; i < a.nWidth; i++)
             {
-                result.pn[i] = a.pn[i] & b.pn[i];
+                if (a.pn[i] != 0)
+                {
+                    return false;
+                }
             }
-            return result;
+            return true;
         }
 
-        public static base_uint operator |(base_uint a, base_uint b)
-        {
-            var result = new base_uint();
-            result.pn = new uint[a.nWidth];
-            for (int i = 0; i < result.nWidth; i++)
-            {
-                result.pn[i] = a.pn[i] | b.pn[i];
-            }
-            return result;
-        }
 
+        #region Comparison operations
         public static bool operator <(base_uint a, base_uint b)
         {
             for (int i = a.nWidth - 1; i >= 0; i--)
@@ -227,7 +185,9 @@ namespace Novacoin
             }
             return true;
         }
+        #endregion
 
+        #region Equality operators
         public static bool operator ==(base_uint a, base_uint b)
         {
             if (object.ReferenceEquals(a, b))
@@ -251,10 +211,12 @@ namespace Novacoin
             {
                 return false;
             }
+
             if (a.pn[1] != (uint)(b >> 32))
             {
                 return false;
             }
+
             for (int i = 2; i < a.nWidth; i++)
             {
                 if (a.pn[i] != 0)
@@ -274,33 +236,49 @@ namespace Novacoin
         {
             return (!(a == b));
         }
-
+        #endregion
+
+        #region Cast operations
+        /// <summary>
+        /// True cast operator
+        /// </summary>
+        /// <param name="a"></param>
+        /// <returns></returns>
         public static bool operator true(base_uint a)
         {
             return (a != 0);
         }
 
+        /// <summary>
+        /// False cast operator.
+        /// </summary>
+        /// <param name="a">Value</param>
+        /// <returns>Boolean result</returns>
         public static bool operator false(base_uint a)
         {
             return (a == 0);
         }
 
+        /// <summary>
+        /// Imlicit byte[] cast operator.
+        /// </summary>
+        /// <param name="a">Value</param>
         public static implicit operator byte[] (base_uint a)
         {
-            var result = new byte[a.nWidth];
-            for (int i = 0; i < a.nWidth; i++)
-            {
-                Buffer.BlockCopy(BitConverter.GetBytes(a.pn[i]), 0, result, 4 * i, 4);
-            }
-            return result;
+            return Interop.LEBytes(a.pn);
         }
-
+        #endregion
+
+        /// <summary>
+        /// Arrays equality checking helper method.
+        /// </summary>
+        /// <param name="a">Array 1</param>
+        /// <param name="b">Array 2</param>
+        /// <returns>Result.</returns>
         private static bool ArraysEqual(uint[] a, uint[] b)
         {
-            if (a.Length != b.Length)
-            {
-                return false;
-            }
+            Contract.Requires<ArgumentException>(a.Length == b.Length, "Array length mismatch.");
+
             for (int i = 0; i < a.Length; i++)
             {
                 if (a[i] != b[i])
@@ -311,19 +289,26 @@ namespace Novacoin
             return true;
         }
 
-        public override int GetHashCode()
+
+        #region IEqualityComparer
+        public bool Equals(base_uint a, base_uint b)
         {
-            int hash = 17;
-            unchecked
+            if (object.ReferenceEquals(a, b))
             {
-                foreach (var element in pn)
-                {
-                    hash = hash * 31 + element.GetHashCode();
-                }
+                return true;
             }
-            return hash;
+
+            return ArraysEqual(a.pn, b.pn);
         }
 
+        public int GetHashCode(base_uint a)
+        {
+            return a.GetHashCode();
+        }
+
+        #endregion
+
+        #region IComparable
         public int CompareTo(base_uint item)
         {
             if (this > item)
@@ -337,15 +322,45 @@ namespace Novacoin
 
             return 0;
         }
+        #endregion
 
+        #region IEquatable
         public bool Equals(base_uint a)
         {
-            if (a == null)
+            if (object.ReferenceEquals(a, null))
             {
                 return false;
             }
 
             return ArraysEqual(pn, a.pn);
         }
+
+        public override int GetHashCode()
+        {
+            int hash = 17;
+            unchecked
+            {
+                foreach (var element in pn)
+                {
+                    hash = hash * 31 + element.GetHashCode();
+                }
+            }
+            return hash;
+        }
+
+        public override bool Equals(object o)
+        {
+            return Equals(o as base_uint);
+        }
+        #endregion
+
+        /// <summary>
+        /// Serialize to string.
+        /// </summary>
+        /// <returns></returns>
+        public override string ToString()
+        {
+            return Interop.ToHex(Interop.ReverseBytes(this));
+        }
     }
 }