DigitsArray.cs

Support File, for use with BigIntX.cs

using System;
using System.Collections.Generic;
using System.Text;
public class DigitsArray
{
public static readonly uint AllBits;
public static readonly uint HiBitSet;
public uint[] Data;
static DigitsArray()
{
unchecked
{
AllBits = ~(uint) 0;
HiBitSet = (uint) 1 << (DataSizeBits - 1);
}
}
public DigitsArray(int size)
{
Allocate(size, 0);
}
public DigitsArray(int size, int used)
{
Allocate(size, used);
}
public DigitsArray(uint[] copyFrom)
{
Allocate(copyFrom.Length);
CopyFrom(copyFrom, 0, 0, copyFrom.Length);
ResetDataUsed();
}
public DigitsArray(DigitsArray copyFrom)
{
Allocate(copyFrom.Count - 1, copyFrom.DataUsed);
Array.Copy(copyFrom.Data, 0, Data, 0, copyFrom.Count);
}
public static int DataSizeOf => sizeof(uint);
public static int DataSizeBits => sizeof(uint) * 8;
public uint this[int index]
{
get
{
if (index < Data.Length)
return Data[index];
return IsNegative ? AllBits : 0;
}
set => Data[index] = value;
}
public int DataUsed
{
get;
set;
}
public int Count => Data.Length;
public bool IsZero => DataUsed == 0 || DataUsed == 1 && Data[0] == 0;
public bool IsNegative => (Data[Data.Length - 1] & HiBitSet) == HiBitSet;
public int Sign
{
get
{
if (Data[0] == 0)
return 0;
if (IsNegative)
return -1;
return 1;
}
}
public void Allocate(int size)
{
Allocate(size, 0);
}
public void Allocate(int size, int used)
{
Data = new uint[size + 1];
DataUsed = used;
}
public void CopyFrom(uint[] source, int sourceOffset, int offset, int length)
{
Array.Copy(source, sourceOffset, Data, 0, length);
}
public void CopyTo(uint[] array, int offset, int length)
{
Array.Copy(Data, 0, array, offset, length);
}
public string GetDataAsString()
{
var result = new StringBuilder();
foreach (var data in Data)
result.Append(data + " ");
return result.ToString();
}
public byte[] ToByteArray()
{
if (Data == null && Sign == 0)
return new byte[1];
uint[] dwords;
byte highByte;
if (Data == null)
{
dwords = new uint[1] {(uint) Sign};
highByte = Sign < 0 ? byte.MaxValue : (byte) 0;
}
else if (Sign == -1)
{
dwords = (uint[]) Data.Clone();
dwords = TwosComplement(dwords);
highByte = byte.MaxValue;
}
else
{
dwords = Data;
highByte = 0;
}
var bytes = new byte[checked(4 * dwords.Length)];
var curByte = 0;
for (var i = 0; i < dwords.Length; ++i)
{
var dword = dwords[i];
for (var j = 0; j < 4; ++j)
{
bytes[curByte++] = (byte) (dword & byte.MaxValue);
dword >>= 8;
}
}
var msb = bytes.Length - 1;
while (msb > 0 && bytes[msb] == highByte)
--msb;
var needExtraByte = (bytes[msb] & 128) != (highByte & 128);
var timmedBytes = new byte[msb + 1 + (needExtraByte ? 1 : 0)];
Array.Copy(bytes, timmedBytes, msb + 1);
if (needExtraByte)
timmedBytes[timmedBytes.Length - 1] = highByte;
return timmedBytes;
}
public uint[] ToUIn32Array()
{
var value = ToByteArray();
var al = value.Length >> 2;
if (al << 2 != value.Length)
al++;
var arr = new uint[al];
Buffer.BlockCopy(value, 0, arr, 0, value.Length);
return arr;
}
public ulong[] ToUIn64Array()
{
var value = ToByteArray();
var al = value.Length >> 3;
if (al << 3 != value.Length)
al++;
var arr = new ulong[al];
Buffer.BlockCopy(value, 0, arr, 0, value.Length);
return arr;
}
private static uint[] TwosComplement(uint[] d)
{
var i = 0;
uint v = 0;
for (; i < d.Length; i++)
{
v = ~d[i] + 1;
d[i] = v;
if (v != 0)
{
i++;
break;
}
}
if (v != 0)
{
for (; i < d.Length; i++)
d[i] = ~d[i];
}
else
{
Array.Resize(ref d, d.Length + 1);
d[d.Length - 1] = 1;
}
return d;
}
public void ResetDataUsed()
{
DataUsed = Data.Length;
if (IsNegative)
{
while (DataUsed > 1 && Data[DataUsed - 1] == AllBits)
--DataUsed;
DataUsed++;
}
else
{
while (DataUsed > 1 && Data[DataUsed - 1] == 0)
--DataUsed;
if (DataUsed == 0)
DataUsed = 1;
}
}
public int ShiftRight(int shiftCount)
{
return ShiftRight(Data, shiftCount);
}
public static int ShiftRight(uint[] buffer, int shiftCount)
{
var shiftAmount = DataSizeBits;
var invShift = 0;
var bufLen = buffer.Length;
while (bufLen > 1 && buffer[bufLen - 1] == 0)
bufLen--;
for (var count = shiftCount; count > 0; count -= shiftAmount)
{
if (count < shiftAmount)
{
shiftAmount = count;
invShift = DataSizeBits - shiftAmount;
}
ulong carry = 0;
for (var i = bufLen - 1; i >= 0; i--)
{
var val = (ulong) buffer[i] >> shiftAmount;
val |= carry;
carry = (ulong) buffer[i] << invShift;
buffer[i] = (uint) val;
}
}
while (bufLen > 1 && buffer[bufLen - 1] == 0)
bufLen--;
return bufLen;
}
public int ShiftLeft(int shiftCount)
{
return ShiftLeft(Data, shiftCount);
}
public static int ShiftLeft(uint[] buffer, int shiftCount)
{
var shiftAmount = DataSizeBits;
var bufLen = buffer.Length;
while (bufLen > 1 && buffer[bufLen - 1] == 0)
bufLen--;
for (var count = shiftCount; count > 0; count -= shiftAmount)
{
if (count < shiftAmount)
shiftAmount = count;
ulong carry = 0;
for (var i = 0; i < bufLen; i++)
{
var val = (ulong) buffer[i] << shiftAmount;
val |= carry;
buffer[i] = (uint) (val & AllBits);
carry = val >> DataSizeBits;
}
if (carry != 0)
{
if (bufLen + 1 <= buffer.Length)
{
buffer[bufLen] = (uint) carry;
bufLen++;
carry = 0;
}
else
{
throw new OverflowException();
}
}
}
return bufLen;
}
public int ShiftLeftWithoutOverflow(int shiftCount)
{
if (shiftCount == 0) return Data.Length;
var temporary = new List<uint>(Data);
var shiftAmount = DataSizeBits;
for (var count = shiftCount; count > 0; count -= shiftAmount)
{
if (count < shiftAmount)
shiftAmount = count;
ulong carry = 0;
for (var i = 0; i < temporary.Count; i++)
{
var val = (ulong) temporary[i] << shiftAmount;
val |= carry;
temporary[i] = (uint) (val & AllBits);
carry = val >> DataSizeBits;
}
if (carry != 0)
{
var lastNum = (uint) carry;
if (IsNegative)
{
var byteCount = (int) Math.Floor(Math.Log(carry, 2));
lastNum = (0xffffffff << byteCount) | (uint) carry;
}
temporary.Add(lastNum);
}
}
Data = new uint[temporary.Count];
temporary.CopyTo(Data);
return Data.Length;
}
}
using System; using System.Collections.Generic; using System.Text; public class DigitsArray { public static readonly uint AllBits; public static readonly uint HiBitSet; public uint[] Data; static DigitsArray() { unchecked { AllBits = ~(uint) 0; HiBitSet = (uint) 1 << (DataSizeBits - 1); } } public DigitsArray(int size) { Allocate(size, 0); } public DigitsArray(int size, int used) { Allocate(size, used); } public DigitsArray(uint[] copyFrom) { Allocate(copyFrom.Length); CopyFrom(copyFrom, 0, 0, copyFrom.Length); ResetDataUsed(); } public DigitsArray(DigitsArray copyFrom) { Allocate(copyFrom.Count - 1, copyFrom.DataUsed); Array.Copy(copyFrom.Data, 0, Data, 0, copyFrom.Count); } public static int DataSizeOf => sizeof(uint); public static int DataSizeBits => sizeof(uint) * 8; public uint this[int index] { get { if (index < Data.Length) return Data[index]; return IsNegative ? AllBits : 0; } set => Data[index] = value; } public int DataUsed { get; set; } public int Count => Data.Length; public bool IsZero => DataUsed == 0 || DataUsed == 1 && Data[0] == 0; public bool IsNegative => (Data[Data.Length - 1] & HiBitSet) == HiBitSet; public int Sign { get { if (Data[0] == 0) return 0; if (IsNegative) return -1; return 1; } } public void Allocate(int size) { Allocate(size, 0); } public void Allocate(int size, int used) { Data = new uint[size + 1]; DataUsed = used; } public void CopyFrom(uint[] source, int sourceOffset, int offset, int length) { Array.Copy(source, sourceOffset, Data, 0, length); } public void CopyTo(uint[] array, int offset, int length) { Array.Copy(Data, 0, array, offset, length); } public string GetDataAsString() { var result = new StringBuilder(); foreach (var data in Data) result.Append(data + " "); return result.ToString(); } public byte[] ToByteArray() { if (Data == null && Sign == 0) return new byte[1]; uint[] dwords; byte highByte; if (Data == null) { dwords = new uint[1] {(uint) Sign}; highByte = Sign < 0 ? byte.MaxValue : (byte) 0; } else if (Sign == -1) { dwords = (uint[]) Data.Clone(); dwords = TwosComplement(dwords); highByte = byte.MaxValue; } else { dwords = Data; highByte = 0; } var bytes = new byte[checked(4 * dwords.Length)]; var curByte = 0; for (var i = 0; i < dwords.Length; ++i) { var dword = dwords[i]; for (var j = 0; j < 4; ++j) { bytes[curByte++] = (byte) (dword & byte.MaxValue); dword >>= 8; } } var msb = bytes.Length - 1; while (msb > 0 && bytes[msb] == highByte) --msb; var needExtraByte = (bytes[msb] & 128) != (highByte & 128); var timmedBytes = new byte[msb + 1 + (needExtraByte ? 1 : 0)]; Array.Copy(bytes, timmedBytes, msb + 1); if (needExtraByte) timmedBytes[timmedBytes.Length - 1] = highByte; return timmedBytes; } public uint[] ToUIn32Array() { var value = ToByteArray(); var al = value.Length >> 2; if (al << 2 != value.Length) al++; var arr = new uint[al]; Buffer.BlockCopy(value, 0, arr, 0, value.Length); return arr; } public ulong[] ToUIn64Array() { var value = ToByteArray(); var al = value.Length >> 3; if (al << 3 != value.Length) al++; var arr = new ulong[al]; Buffer.BlockCopy(value, 0, arr, 0, value.Length); return arr; } private static uint[] TwosComplement(uint[] d) { var i = 0; uint v = 0; for (; i < d.Length; i++) { v = ~d[i] + 1; d[i] = v; if (v != 0) { i++; break; } } if (v != 0) { for (; i < d.Length; i++) d[i] = ~d[i]; } else { Array.Resize(ref d, d.Length + 1); d[d.Length - 1] = 1; } return d; } public void ResetDataUsed() { DataUsed = Data.Length; if (IsNegative) { while (DataUsed > 1 && Data[DataUsed - 1] == AllBits) --DataUsed; DataUsed++; } else { while (DataUsed > 1 && Data[DataUsed - 1] == 0) --DataUsed; if (DataUsed == 0) DataUsed = 1; } } public int ShiftRight(int shiftCount) { return ShiftRight(Data, shiftCount); } public static int ShiftRight(uint[] buffer, int shiftCount) { var shiftAmount = DataSizeBits; var invShift = 0; var bufLen = buffer.Length; while (bufLen > 1 && buffer[bufLen - 1] == 0) bufLen--; for (var count = shiftCount; count > 0; count -= shiftAmount) { if (count < shiftAmount) { shiftAmount = count; invShift = DataSizeBits - shiftAmount; } ulong carry = 0; for (var i = bufLen - 1; i >= 0; i--) { var val = (ulong) buffer[i] >> shiftAmount; val |= carry; carry = (ulong) buffer[i] << invShift; buffer[i] = (uint) val; } } while (bufLen > 1 && buffer[bufLen - 1] == 0) bufLen--; return bufLen; } public int ShiftLeft(int shiftCount) { return ShiftLeft(Data, shiftCount); } public static int ShiftLeft(uint[] buffer, int shiftCount) { var shiftAmount = DataSizeBits; var bufLen = buffer.Length; while (bufLen > 1 && buffer[bufLen - 1] == 0) bufLen--; for (var count = shiftCount; count > 0; count -= shiftAmount) { if (count < shiftAmount) shiftAmount = count; ulong carry = 0; for (var i = 0; i < bufLen; i++) { var val = (ulong) buffer[i] << shiftAmount; val |= carry; buffer[i] = (uint) (val & AllBits); carry = val >> DataSizeBits; } if (carry != 0) { if (bufLen + 1 <= buffer.Length) { buffer[bufLen] = (uint) carry; bufLen++; carry = 0; } else { throw new OverflowException(); } } } return bufLen; } public int ShiftLeftWithoutOverflow(int shiftCount) { if (shiftCount == 0) return Data.Length; var temporary = new List<uint>(Data); var shiftAmount = DataSizeBits; for (var count = shiftCount; count > 0; count -= shiftAmount) { if (count < shiftAmount) shiftAmount = count; ulong carry = 0; for (var i = 0; i < temporary.Count; i++) { var val = (ulong) temporary[i] << shiftAmount; val |= carry; temporary[i] = (uint) (val & AllBits); carry = val >> DataSizeBits; } if (carry != 0) { var lastNum = (uint) carry; if (IsNegative) { var byteCount = (int) Math.Floor(Math.Log(carry, 2)); lastNum = (0xffffffff << byteCount) | (uint) carry; } temporary.Add(lastNum); } } Data = new uint[temporary.Count]; temporary.CopyTo(Data); return Data.Length; } }
using System;
using System.Collections.Generic;
using System.Text;
public class DigitsArray
{
    public static readonly uint   AllBits;
    public static readonly uint   HiBitSet;
    public                 uint[] Data;
    static DigitsArray()
    {
        unchecked
        {
            AllBits  = ~(uint) 0;
            HiBitSet = (uint) 1 << (DataSizeBits - 1);
        }
    }
    public DigitsArray(int size)
    {
        Allocate(size, 0);
    }
    public DigitsArray(int size, int used)
    {
        Allocate(size, used);
    }
    public DigitsArray(uint[] copyFrom)
    {
        Allocate(copyFrom.Length);
        CopyFrom(copyFrom, 0, 0, copyFrom.Length);
        ResetDataUsed();
    }
    public DigitsArray(DigitsArray copyFrom)
    {
        Allocate(copyFrom.Count - 1, copyFrom.DataUsed);
        Array.Copy(copyFrom.Data, 0, Data, 0, copyFrom.Count);
    }
    public static int DataSizeOf   => sizeof(uint);
    public static int DataSizeBits => sizeof(uint) * 8;
    public uint this[int index]
    {
        get
        {
            if (index < Data.Length)
                return Data[index];
            return IsNegative ? AllBits : 0;
        }
        set => Data[index] = value;
    }
    public int DataUsed
    {
        get;
        set;
    }
    public int  Count      => Data.Length;
    public bool IsZero     => DataUsed == 0 || DataUsed == 1 && Data[0] == 0;
    public bool IsNegative => (Data[Data.Length - 1] & HiBitSet) == HiBitSet;
    public int Sign
    {
        get
        {
            if (Data[0] == 0)
                return 0;
            if (IsNegative)
                return -1;
            return 1;
        }
    }
    public void Allocate(int size)
    {
        Allocate(size, 0);
    }
    public void Allocate(int size, int used)
    {
        Data     = new uint[size + 1];
        DataUsed = used;
    }
    public void CopyFrom(uint[] source, int sourceOffset, int offset, int length)
    {
        Array.Copy(source, sourceOffset, Data, 0, length);
    }
    public void CopyTo(uint[] array, int offset, int length)
    {
        Array.Copy(Data, 0, array, offset, length);
    }
    public string GetDataAsString()
    {
        var result = new StringBuilder();
        foreach (var data in Data)
            result.Append(data + " ");
        return result.ToString();
    }
    public byte[] ToByteArray()
    {
        if (Data == null && Sign == 0)
            return new byte[1];
        uint[] dwords;
        byte   highByte;
        if (Data == null)
        {
            dwords   = new uint[1] {(uint) Sign};
            highByte = Sign < 0 ? byte.MaxValue : (byte) 0;
        }
        else if (Sign == -1)
        {
            dwords   = (uint[]) Data.Clone();
            dwords   = TwosComplement(dwords);
            highByte = byte.MaxValue;
        }
        else
        {
            dwords   = Data;
            highByte = 0;
        }
        var bytes   = new byte[checked(4 * dwords.Length)];
        var curByte = 0;
        for (var i = 0; i < dwords.Length; ++i)
        {
            var dword = dwords[i];
            for (var j = 0; j < 4; ++j)
            {
                bytes[curByte++] =   (byte) (dword & byte.MaxValue);
                dword            >>= 8;
            }
        }
        var msb = bytes.Length - 1;
        while (msb > 0 && bytes[msb] == highByte)
            --msb;
        var needExtraByte = (bytes[msb] & 128) != (highByte & 128);
        var timmedBytes   = new byte[msb + 1 + (needExtraByte ? 1 : 0)];
        Array.Copy(bytes, timmedBytes, msb + 1);
        if (needExtraByte)
            timmedBytes[timmedBytes.Length - 1] = highByte;
        return timmedBytes;
    }
    public uint[] ToUIn32Array()
    {
        var value = ToByteArray();
        var al    = value.Length >> 2;
        if (al << 2 != value.Length)
            al++;
        var arr = new uint[al];
        Buffer.BlockCopy(value, 0, arr, 0, value.Length);
        return arr;
    }
    public ulong[] ToUIn64Array()
    {
        var value = ToByteArray();
        var al    = value.Length >> 3;
        if (al << 3 != value.Length)
            al++;
        var arr = new ulong[al];
        Buffer.BlockCopy(value, 0, arr, 0, value.Length);
        return arr;
    }
    private static uint[] TwosComplement(uint[] d)
    {
        var  i = 0;
        uint v = 0;
        for (; i < d.Length; i++)
        {
            v    = ~d[i] + 1;
            d[i] = v;
            if (v != 0)
            {
                i++;
                break;
            }
        }
        if (v != 0)
        {
            for (; i < d.Length; i++)
                d[i] = ~d[i];
        }
        else
        {
            Array.Resize(ref d, d.Length + 1);
            d[d.Length - 1] = 1;
        }
        return d;
    }
    public void ResetDataUsed()
    {
        DataUsed = Data.Length;
        if (IsNegative)
        {
            while (DataUsed > 1 && Data[DataUsed - 1] == AllBits)
                --DataUsed;
            DataUsed++;
        }
        else
        {
            while (DataUsed > 1 && Data[DataUsed - 1] == 0)
                --DataUsed;
            if (DataUsed == 0)
                DataUsed = 1;
        }
    }
    public int ShiftRight(int shiftCount)
    {
        return ShiftRight(Data, shiftCount);
    }
    public static int ShiftRight(uint[] buffer, int shiftCount)
    {
        var shiftAmount = DataSizeBits;
        var invShift    = 0;
        var bufLen      = buffer.Length;
        while (bufLen > 1 && buffer[bufLen - 1] == 0)
            bufLen--;
        for (var count = shiftCount; count > 0; count -= shiftAmount)
        {
            if (count < shiftAmount)
            {
                shiftAmount = count;
                invShift    = DataSizeBits - shiftAmount;
            }
            ulong carry = 0;
            for (var i = bufLen - 1; i >= 0; i--)
            {
                var val = (ulong) buffer[i] >> shiftAmount;
                val       |= carry;
                carry     =  (ulong) buffer[i] << invShift;
                buffer[i] =  (uint) val;
            }
        }
        while (bufLen > 1 && buffer[bufLen - 1] == 0)
            bufLen--;
        return bufLen;
    }
    public int ShiftLeft(int shiftCount)
    {
        return ShiftLeft(Data, shiftCount);
    }
    public static int ShiftLeft(uint[] buffer, int shiftCount)
    {
        var shiftAmount = DataSizeBits;
        var bufLen      = buffer.Length;
        while (bufLen > 1 && buffer[bufLen - 1] == 0)
            bufLen--;
        for (var count = shiftCount; count > 0; count -= shiftAmount)
        {
            if (count < shiftAmount)
                shiftAmount = count;
            ulong carry = 0;
            for (var i = 0; i < bufLen; i++)
            {
                var val = (ulong) buffer[i] << shiftAmount;
                val       |= carry;
                buffer[i] =  (uint) (val & AllBits);
                carry     =  val >> DataSizeBits;
            }
            if (carry != 0)
            {
                if (bufLen + 1 <= buffer.Length)
                {
                    buffer[bufLen] = (uint) carry;
                    bufLen++;
                    carry = 0;
                }
                else
                {
                    throw new OverflowException();
                }
            }
        }
        return bufLen;
    }
    public int ShiftLeftWithoutOverflow(int shiftCount)
    {
        if (shiftCount == 0) return Data.Length;
        var temporary   = new List<uint>(Data);
        var shiftAmount = DataSizeBits;
        for (var count = shiftCount; count > 0; count -= shiftAmount)
        {
            if (count < shiftAmount)
                shiftAmount = count;
            ulong carry = 0;
            for (var i = 0; i < temporary.Count; i++)
            {
                var val = (ulong) temporary[i] << shiftAmount;
                val          |= carry;
                temporary[i] =  (uint) (val & AllBits);
                carry        =  val >> DataSizeBits;
            }
            if (carry != 0)
            {
                var lastNum = (uint) carry;
                if (IsNegative)
                {
                    var byteCount = (int) Math.Floor(Math.Log(carry, 2));
                    lastNum = (0xffffffff << byteCount) | (uint) carry;
                }
                temporary.Add(lastNum);
            }
        }
        Data = new uint[temporary.Count];
        temporary.CopyTo(Data);
        return Data.Length;
    }
}