/**
* 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;
namespace Novacoin
{
public class base_uint : IComparable, IEquatable
{
protected int nWidth;
protected uint[] pn;
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
{
get
{
return nWidth;
}
}
public static bool operator !(base_uint a)
{
for (int i = 0; i < a.nWidth; i++)
{
if (a.pn[i] != 0)
{
return false;
}
}
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;
}
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];
}
ret++;
return ret;
}
public static base_uint operator ++(base_uint a)
{
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;
}
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;
}
public static base_uint operator +(base_uint a, base_uint b)
{
var result = new base_uint();
ulong carry = 0;
for (int i = 0; i < result.nWidth; i++)
{
ulong n = carry + a.pn[i] + b.pn[i];
result.pn[i] = (uint)(n & 0xffffffff);
carry = n >> 32;
}
return result;
}
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)
{
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;
}
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;
}
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)
{
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)
{
if (object.ReferenceEquals(a, b))
{
return true;
}
for (int i = 0; i < a.nWidth; i++)
{
if (a.pn[i] != b.pn[i])
{
return false;
}
}
return true;
}
public static bool operator ==(base_uint a, ulong b)
{
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++)
{
if (a.pn[i] != 0)
{
return false;
}
}
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));
}
public static bool operator true(base_uint a)
{
return (a != 0);
}
public static bool operator false(base_uint a)
{
return (a == 0);
}
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;
}
private static bool ArraysEqual(uint[] a, uint[] b)
{
if (a.Length != b.Length)
{
return false;
}
for (int i = 0; i < a.Length; i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
public override int GetHashCode()
{
int hash = 17;
unchecked
{
foreach (var element in pn)
{
hash = hash * 31 + element.GetHashCode();
}
}
return hash;
}
public int CompareTo(base_uint item)
{
if (this > item)
{
return 1;
}
else if (this < item)
{
return -1;
}
return 0;
}
public bool Equals(base_uint a)
{
if (a == null)
{
return false;
}
return ArraysEqual(pn, a.pn);
}
}
}