X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=Novacoin%2Fbase_uint.cs;h=adfa75f0f735c1ddf68fab0611fd85b74e4a45b9;hb=1dcac5faa2b1477034f82466ffb16170fa2e9bb6;hp=287be58af5f9faeb28168dc458243febbf4be5e1;hpb=975d1cfb855777d6c04a7827d8417004633441f1;p=NovacoinLibrary.git diff --git a/Novacoin/base_uint.cs b/Novacoin/base_uint.cs index 287be58..adfa75f 100644 --- a/Novacoin/base_uint.cs +++ b/Novacoin/base_uint.cs @@ -1,16 +1,113 @@ -using System; +/** +* Novacoin classes library +* Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com) + +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. + +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +*/ + + +using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Diagnostics.Contracts; namespace Novacoin { - public class base_uint + /// + /// Base class for uint256 and uint160. + /// + public class base_uint : IComparable, IEquatable, IEqualityComparer { - protected uint nWidth; + #region Internal representation + /// + /// Length of internal representation + /// + protected int nWidth; + /// + /// Big numbers are stored as array of unsigned 32-bit integers. + /// protected uint[] pn; + #endregion + + #region Helper properties + public double Double + { + get + { + 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 Low64 + { + get { return pn[0] | (ulong)pn[1] << 32; } + } + public uint Low32 + { + get { return pn[0]; } + } + + /// + /// Total size in bytes. + /// + public int Size + { + get + { + return nWidth * sizeof(uint); + } + } + + /// + /// Zero or the position of highest non-zero bit plus one. + /// + protected int bits + { + get + { + 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; + } + } + #endregion + + + /// + /// Negation operator + /// + /// Value + /// True if value is zero, false otherwise. public static bool operator !(base_uint a) { for (int i = 0; i < a.nWidth; i++) @@ -23,74 +120,247 @@ namespace Novacoin return true; } - public static base_uint operator ~(base_uint a) + + #region Comparison operations + public static bool operator <(base_uint a, base_uint b) + { + for (int i = a.nWidth - 1; i >= 0; i--) + { + if (a.pn[i] < b.pn[i]) + { + return true; + } + else if (a.pn[i] > b.pn[i]) + { + return false; + } + } + return false; + } + + public static bool operator <=(base_uint a, base_uint b) + { + for (int i = a.nWidth - 1; i >= 0; i--) + { + if (a.pn[i] < b.pn[i]) + { + return true; + } + else if (a.pn[i] > b.pn[i]) + { + return false; + } + } + return true; + } + + public static bool operator >(base_uint a, base_uint b) { - var ret = new base_uint(); - for (int i = 0; i < a.nWidth; i++) + for (int i = a.nWidth - 1; i >= 0; i--) { - ret.pn[i] = ~a.pn[i]; + if (a.pn[i] > b.pn[i]) + { + return true; + } + else if (a.pn[i] < b.pn[i]) + { + return false; + } } - return ret; + return false; } - public static base_uint operator -(base_uint a) + public static bool operator >=(base_uint a, base_uint b) { - var ret = new base_uint(); + for (int i = a.nWidth - 1; i >= 0; i--) + { + if (a.pn[i] > b.pn[i]) + { + return true; + } + else if (a.pn[i] < b.pn[i]) + { + return false; + } + } + return true; + } + #endregion + + #region Equality operators + public static bool operator ==(base_uint a, base_uint b) + { + if (object.ReferenceEquals(a, b)) + { + return true; + } + for (int i = 0; i < a.nWidth; i++) { - ret.pn[i] = ~a.pn[i]; + if (a.pn[i] != b.pn[i]) + { + return false; + } } - ret++; - return ret; + return true; } - public static base_uint operator ++(base_uint a) + public static bool operator ==(base_uint a, ulong b) { - // prefix operator - int i = 0; - while (++a.pn[i] == 0 && i < a.nWidth - 1) + if (a.pn[0] != (uint)b) + { + return false; + } + + if (a.pn[1] != (uint)(b >> 32)) + { + return false; + } + + for (int i = 2; i < a.nWidth; i++) { - i++; + if (a.pn[i] != 0) + { + return false; + } } - return a; + return true; + } + + public static bool operator !=(base_uint a, base_uint b) + { + return (!(a == b)); + } + + public static bool operator !=(base_uint a, ulong b) + { + return (!(a == b)); + } + #endregion + + #region Cast oerations + /// + /// True cast operator + /// + /// + /// + public static bool operator true(base_uint a) + { + return (a != 0); + } + + /// + /// False cast operator. + /// + /// Value + /// Boolean result + public static bool operator false(base_uint a) + { + return (a == 0); } - public static base_uint operator --(base_uint a) + /// + /// Imlicit byte[] cast operator. + /// + /// Value + public static implicit operator byte[] (base_uint a) { - // prefix operator - int i = 0; - while (--a.pn[i] == uint.MaxValue && i < a.nWidth - 1) + return Interop.LEBytes(a.pn); + } + #endregion + + /// + /// Arrays equality checking helper method. + /// + /// Array 1 + /// Array 2 + /// Result. + private static bool ArraysEqual(uint[] a, uint[] b) + { + Contract.Requires(a.Length == b.Length, "Array length mismatch."); + + for (int i = 0; i < a.Length; i++) { - i++; + if (a[i] != b[i]) + { + return false; + } } - return a; + return true; } - public static base_uint operator ^(base_uint a, base_uint b) + + #region IEqualityComparer + public bool Equals(base_uint a, base_uint b) { - var c = new base_uint(); - c.pn = new uint[a.nWidth]; - for (int i = 0; i < c.nWidth; i++) + if (object.ReferenceEquals(a, b)) { - c.pn[i] = a.pn[i] ^ b.pn[i]; + return true; } - return c; + + return ArraysEqual(a.pn, b.pn); + } + + public int GetHashCode(base_uint a) + { + return a.GetHashCode(); } - public static base_uint operator +(base_uint a, base_uint b) + #endregion + + #region IComparable + public int CompareTo(base_uint item) { - var result = new base_uint(); - ulong carry = 0; - for (int i = 0; i < result.nWidth; i++) + if (this > item) + { + return 1; + } + else if (this < item) { - ulong n = carry + a.pn[i] + b.pn[i]; - result.pn[i] = (uint)(n & 0xffffffff); - carry = n >> 32; + return -1; } - return result; + + return 0; } + #endregion + #region IEquatable + public bool Equals(base_uint a) + { + 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 + /// + /// Serialize to string. + /// + /// + public override string ToString() + { + return Interop.ToHex(Interop.ReverseBytes(this)); + } } }