nel-neo-thinsdk
Version:
817 lines (747 loc) • 31.8 kB
text/typescript
///<reference path="UintVariable.ts"/>
///<reference path="Uint64.ts"/>
namespace Neo
{
const DB = 26;
const DM = (1 << DB) - 1;
const DV = DM + 1;
let _minusone: BigInteger, _one: BigInteger, _zero: BigInteger;
export class BigInteger
{
private _sign = 0;
private _bits = new Array<number>();
public static get MinusOne() { return _minusone || (_minusone = new BigInteger(-1)); }
public static get One() { return _one || (_one = new BigInteger(1)); }
public static get Zero() { return _zero || (_zero = new BigInteger(0)); }
constructor(value: number | string | ArrayBuffer | Uint8Array)
{
if (typeof value === "number")
{
if (!isFinite(value) || isNaN(value)) throw new RangeError();
let parts = BigInteger.getDoubleParts(value);
if (parts.man.equals(Uint64.Zero) || parts.exp <= -64) return;
if (parts.exp <= 0)
{
this.fromUint64(parts.man.rightShift(-parts.exp), parts.sign);
}
else if (parts.exp <= 11)
{
this.fromUint64(parts.man.leftShift(parts.exp), parts.sign);
}
else
{
parts.man = parts.man.leftShift(11);
parts.exp -= 11;
let units = Math.ceil((parts.exp + 64) / DB);
let cu = Math.ceil(parts.exp / DB);
let cbit = cu * DB - parts.exp;
for (let i = cu; i < units; i++)
this._bits[i] = parts.man.rightShift(cbit + (i - cu) * DB).toUint32() & DM;
if (cbit > 0)
this._bits[cu - 1] = (parts.man.toUint32() << (DB - cbit)) & DM;
this._sign = parts.sign;
this.clamp();
}
}
else if (typeof value === "string")
{
this.fromString(value);
}
else if (value instanceof Uint8Array)
{
this.fromUint8Array(value);
}
else if (value instanceof ArrayBuffer)
{
this.fromUint8Array(new Uint8Array(value));
}
}
public static add(x: number | BigInteger, y: number | BigInteger): BigInteger
{
let bi_x = typeof x === "number" ? new BigInteger(x) : x;
let bi_y = typeof y === "number" ? new BigInteger(y) : y;
if (bi_x._sign == 0) return bi_y;
if (bi_y._sign == 0) return bi_x;
if ((bi_x._sign > 0) != (bi_y._sign > 0))
return BigInteger.subtract(bi_x, bi_y.negate());
let bits_r = new Array<number>();
BigInteger.addTo(bi_x._bits, bi_y._bits, bits_r);
return BigInteger.create(bi_x._sign, bits_r);
}
public add(other: number | BigInteger): BigInteger
{
return BigInteger.add(this, other);
}
private static addTo(x: Array<number>, y: Array<number>, r: Array<number>): void
{
if (x.length < y.length)
{
let t = x;
x = y;
y = t;
}
let c = 0, i = 0;
while (i < y.length)
{
c += x[i] + y[i];
r[i++] = c & DM;
c >>>= DB;
}
while (i < x.length)
{
c += x[i];
r[i++] = c & DM;
c >>>= DB;
}
if (c > 0)
r[i] = c;
}
public bitLength(): number
{
let l = this._bits.length;
if (l == 0) return 0;
return --l * DB + BigInteger.bitLengthInternal(this._bits[l]);
}
private static bitLengthInternal(w: number): number
{
return (w < 1 << 15 ? (w < 1 << 7
? (w < 1 << 3 ? (w < 1 << 1
? (w < 1 << 0 ? (w < 0 ? 32 : 0) : 1)
: (w < 1 << 2 ? 2 : 3)) : (w < 1 << 5
? (w < 1 << 4 ? 4 : 5)
: (w < 1 << 6 ? 6 : 7)))
: (w < 1 << 11
? (w < 1 << 9 ? (w < 1 << 8 ? 8 : 9) : (w < 1 << 10 ? 10 : 11))
: (w < 1 << 13 ? (w < 1 << 12 ? 12 : 13) : (w < 1 << 14 ? 14 : 15)))) : (w < 1 << 23 ? (w < 1 << 19
? (w < 1 << 17 ? (w < 1 << 16 ? 16 : 17) : (w < 1 << 18 ? 18 : 19))
: (w < 1 << 21 ? (w < 1 << 20 ? 20 : 21) : (w < 1 << 22 ? 22 : 23))) : (w < 1 << 27
? (w < 1 << 25 ? (w < 1 << 24 ? 24 : 25) : (w < 1 << 26 ? 26 : 27))
: (w < 1 << 29 ? (w < 1 << 28 ? 28 : 29) : (w < 1 << 30 ? 30 : 31)))));
}
private clamp(): void
{
let l = this._bits.length;
while (l > 0 && (this._bits[--l] | 0) == 0)
this._bits.pop();
while (l > 0)
this._bits[--l] |= 0;
if (this._bits.length == 0)
this._sign = 0;
}
public static compare(x: number | BigInteger, y: number | BigInteger): number
{
let bi_x = typeof x === "number" ? new BigInteger(x) : x;
let bi_y = typeof y === "number" ? new BigInteger(y) : y;
if (bi_x._sign >= 0 && bi_y._sign < 0) return +1;
if (bi_x._sign < 0 && bi_y._sign >= 0) return -1;
let c = BigInteger.compareAbs(bi_x, bi_y);
return bi_x._sign < 0 ? -c : c;
}
private static compareAbs(x: BigInteger, y: BigInteger): number
{
if (x._bits.length > y._bits.length) return +1;
if (x._bits.length < y._bits.length) return -1;
for (let i = x._bits.length - 1; i >= 0; i--)
if (x._bits[i] > y._bits[i])
return +1;
else if (x._bits[i] < y._bits[i])
return -1;
return 0;
}
public compareTo(other: number | BigInteger): number
{
return BigInteger.compare(this, other);
}
private static create(sign: number, bits: number[], clamp = false): BigInteger
{
let bi: BigInteger = Object.create(BigInteger.prototype);
bi._sign = sign;
bi._bits = bits;
if (clamp) bi.clamp();
return bi;
}
public static divide(x: number | BigInteger, y: number | BigInteger): BigInteger
{
let bi_x = typeof x === "number" ? new BigInteger(x) : x;
let bi_y = typeof y === "number" ? new BigInteger(y) : y;
return BigInteger.divRem(bi_x, bi_y).result;
}
public divide(other: number | BigInteger): BigInteger
{
return BigInteger.divide(this, other);
}
public static divRem(x: number | BigInteger, y: number | BigInteger): { result: BigInteger, remainder: BigInteger }
{
let bi_x = typeof x === "number" ? new BigInteger(x) : x;
let bi_y = typeof y === "number" ? new BigInteger(y) : y;
if (bi_y._sign == 0) throw new RangeError();
if (bi_x._sign == 0) return { result: BigInteger.Zero, remainder: BigInteger.Zero };
if (bi_y._sign == 1 && bi_y._bits == null) return { result: bi_x, remainder: BigInteger.Zero };
if (bi_y._sign == -1 && bi_y._bits == null) return { result: bi_x.negate(), remainder: BigInteger.Zero };
let sign_result = (bi_x._sign > 0) == (bi_y._sign > 0) ? +1 : -1;
let c = BigInteger.compareAbs(bi_x, bi_y);
if (c == 0) return { result: sign_result > 0 ? BigInteger.One : BigInteger.MinusOne, remainder: BigInteger.Zero };
if (c < 0) return { result: BigInteger.Zero, remainder: bi_x };
let bits_result = new Array<number>();
let bits_rem = new Array<number>();
Array.copy(bi_x._bits, 0, bits_rem, 0, bi_x._bits.length);
let df = bi_y._bits[bi_y._bits.length - 1];
for (let i = bi_x._bits.length - 1; i >= bi_y._bits.length - 1; i--)
{
let offset = i - bi_y._bits.length + 1;
let d = bits_rem[i] + (bits_rem[i + 1] || 0) * DV;
let max = Math.floor(d / df);
if (max > DM) max = DM;
let min = 0;
while (min != max)
{
let bits_sub = new Array<number>(offset + bi_y._bits.length);
for (let i = 0; i < offset; i++)bits_sub[i] = 0;
bits_result[offset] = Math.ceil((min + max) / 2);
BigInteger.multiplyTo(bi_y._bits, [bits_result[offset]], bits_sub, offset);
if (BigInteger.subtractTo(bits_rem, bits_sub))
max = bits_result[offset] - 1;
else
min = bits_result[offset];
}
let bits_sub = new Array<number>(offset + bi_y._bits.length);
for (let i = 0; i < offset; i++)bits_sub[i] = 0;
bits_result[offset] = min;
BigInteger.multiplyTo(bi_y._bits, [bits_result[offset]], bits_sub, offset);
BigInteger.subtractTo(bits_rem, bits_sub, bits_rem);
}
return { result: BigInteger.create(sign_result, bits_result, true), remainder: BigInteger.create(bi_x._sign, bits_rem, true) };
}
public static equals(x: number | BigInteger, y: number | BigInteger): boolean
{
let bi_x = typeof x === "number" ? new BigInteger(x) : x;
let bi_y = typeof y === "number" ? new BigInteger(y) : y;
if (bi_x._sign != bi_y._sign) return false;
if (bi_x._bits.length != bi_y._bits.length) return false;
for (let i = 0; i < bi_x._bits.length; i++)
if (bi_x._bits[i] != bi_y._bits[i])
return false;
return true;
}
public equals(other: number | BigInteger): boolean
{
return BigInteger.equals(this, other);
}
public static fromString(str: string, radix = 10): BigInteger
{
let bi = Object.create(BigInteger.prototype) as BigInteger;
bi.fromString(str, radix);
return bi;
}
private fromString(str: string, radix = 10): void
{
if (radix < 2 || radix > 36) throw new RangeError();
if (str.length == 0)
{
this._sign == 0;
this._bits = [];
return;
}
let bits_radix = [radix];
let bits_a = [0];
let first = str.charCodeAt(0);
let withsign = first == 0x2b || first == 0x2d;
this._sign = first == 0x2d ? -1 : +1;
this._bits = [];
for (let i = withsign ? 1 : 0; i < str.length; i++)
{
bits_a[0] = str.charCodeAt(i);
if (bits_a[0] >= 0x30 && bits_a[0] <= 0x39) bits_a[0] -= 0x30;
else if (bits_a[0] >= 0x41 && bits_a[0] <= 0x5a) bits_a[0] -= 0x37;
else if (bits_a[0] >= 0x61 && bits_a[0] <= 0x7a) bits_a[0] -= 0x57;
else throw new RangeError();
let bits_temp = new Array<number>();
BigInteger.multiplyTo(this._bits, bits_radix, bits_temp);
BigInteger.addTo(bits_temp, bits_a, this._bits);
}
this.clamp();
}
public static fromUint8Array(arr: Uint8Array, sign = 1, littleEndian = true): BigInteger
{
let bi = Object.create(BigInteger.prototype) as BigInteger;
bi.fromUint8Array(arr, sign, littleEndian);
return bi;
}
public static fromUint8ArrayAutoSign(arr: Uint8Array, littleEndian = true): BigInteger
{
var spos: number = littleEndian ? arr.length - 1 : 0;
var btsign = arr[spos];
var care = (btsign & 128);
if (care > 0)
{//负数
var array = new Uint8Array(arr.length);
for (var i = 0; i < arr.length; i++)
{
array[i] = ~arr[i];
}
//btsign &= (~0x80);//高位归零
//array[spos] = btsign;
var n = BigInteger.fromUint8Array(array, 1, littleEndian);
n = n.add(1);
n["_sign"] = -1;
return n;
}
return BigInteger.fromUint8Array(arr, 1, littleEndian);
}
private fromUint8Array(arr: Uint8Array, sign = 1, littleEndian = true): void
{
if (!littleEndian)
{
let arr_new = new Uint8Array(arr.length);
for (let i = 0; i < arr.length; i++)
arr_new[arr.length - 1 - i] = arr[i];
arr = arr_new;
}
let actual_length = BigInteger.getActualLength(arr);
let bits = actual_length * 8;
let units = Math.ceil(bits / DB);
this._bits = [];
for (let i = 0; i < units; i++)
{
let cb = i * DB;
let cu = Math.floor(cb / 8);
cb %= 8;
this._bits[i] = ((arr[cu] | arr[cu + 1] << 8 | arr[cu + 2] << 16 | arr[cu + 3] << 24) >>> cb) & DM;
}
this._sign = sign < 0 ? -1 : +1;
this.clamp();
}
private fromUint64(i: Uint64, sign: number): void
{
while (i.bits[0] != 0 || i.bits[1] != 0)
{
this._bits.push(i.toUint32() & DM);
i = i.rightShift(DB);
}
this._sign = sign;
this.clamp();
}
private static getActualLength(arr: ArrayLike<number>): number
{
let actual_length = arr.length;
for (let i = arr.length - 1; i >= 0; i--)
if (arr[i] != 0)
{
actual_length = i + 1;
break;
}
return actual_length;
}
private static getDoubleParts(dbl: number)
{
let uu = new Uint32Array(2);
new Float64Array(uu.buffer)[0] = dbl;
let result = {
sign: 1 - ((uu[1] >>> 30) & 2),
man: new Uint64(uu[0], uu[1] & 0x000FFFFF),
exp: (uu[1] >>> 20) & 0x7FF,
fFinite: true
};
if (result.exp == 0)
{
if (!result.man.equals(Uint64.Zero))
result.exp = -1074;
}
else if (result.exp == 0x7FF)
{
result.fFinite = false;
}
else
{
result.man = result.man.or(new Uint64(0, 0x00100000));
result.exp -= 1075;
}
return result;
}
public getLowestSetBit(): number
{
if (this._sign == 0) return -1;
let w = 0;
while (this._bits[w] == 0) w++;
for (let x = 0; x < DB; x++)
if ((this._bits[w] & 1 << x) > 0)
return x + w * DB;
}
public isEven(): boolean
{
if (this._sign == 0) return true;
return (this._bits[0] & 1) == 0;
}
public isZero(): boolean
{
return this._sign == 0;
}
public leftShift(shift: number): BigInteger
{
if (shift == 0) return this;
let shift_units = Math.floor(shift / DB);
shift %= DB;
let bits_new = new Array<number>(this._bits.length + shift_units);
if (shift == 0)
{
for (let i = 0; i < this._bits.length; i++)
bits_new[i + shift_units] = this._bits[i];
}
else
{
for (let i = shift_units; i < bits_new.length; i++)
bits_new[i] = (this._bits[i - shift_units] << shift | this._bits[i - shift_units - 1] >>> (DB - shift)) & DM;
bits_new[bits_new.length] = this._bits[this._bits.length - 1] >>> (DB - shift) & DM;
}
return BigInteger.create(this._sign, bits_new, true);
}
public static mod(x: number | BigInteger, y: number | BigInteger): BigInteger
{
let bi_x = typeof x === "number" ? new BigInteger(x) : x;
let bi_y = typeof y === "number" ? new BigInteger(y) : y;
let bi_new = BigInteger.divRem(bi_x, bi_y).remainder;
if (bi_new._sign < 0)
bi_new = BigInteger.add(bi_new, bi_y);
return bi_new;
}
public mod(other: number | BigInteger): BigInteger
{
return BigInteger.mod(this, other);
}
public static modInverse(value: number | BigInteger, modulus: number | BigInteger): BigInteger
{
let a = typeof value === "number" ? new BigInteger(value) : value;
let n = typeof modulus === "number" ? new BigInteger(modulus) : modulus;
let i = n, v = BigInteger.Zero, d = BigInteger.One;
while (a._sign > 0)
{
let t = BigInteger.divRem(i, a);
let x = d;
i = a;
a = t.remainder;
d = v.subtract(t.result.multiply(x));
v = x;
}
return BigInteger.mod(v, n);
}
public modInverse(modulus: number | BigInteger): BigInteger
{
return BigInteger.modInverse(this, modulus);
}
public static modPow(value: number | BigInteger, exponent: number | BigInteger, modulus: number | BigInteger): BigInteger
{
let bi_v = typeof value === "number" ? new BigInteger(value) : value;
let bi_e = typeof exponent === "number" ? new BigInteger(exponent) : exponent;
let bi_m = typeof modulus === "number" ? new BigInteger(modulus) : modulus;
if (bi_e._sign < 0 || bi_m._sign == 0) throw new RangeError();
if (Math.abs(bi_m._sign) == 1 && bi_m._bits == null) return BigInteger.Zero;
let h = bi_e.bitLength();
let bi_new = BigInteger.One;
for (let i = 0; i < h; i++)
{
if (i > 0)
bi_v = BigInteger.multiply(bi_v, bi_v);
bi_v = bi_v.remainder(bi_m);
if (bi_e.testBit(i))
bi_new = BigInteger.multiply(bi_v, bi_new).remainder(bi_m);
}
if (bi_new._sign < 0)
bi_new = BigInteger.add(bi_new, bi_m);
return bi_new;
}
public modPow(exponent: number | BigInteger, modulus: number | BigInteger): BigInteger
{
return BigInteger.modPow(this, exponent, modulus);
}
public static multiply(x: number | BigInteger, y: number | BigInteger): BigInteger
{
let bi_x = typeof x === "number" ? new BigInteger(x) : x;
let bi_y = typeof y === "number" ? new BigInteger(y) : y;
if (bi_x._sign == 0) return bi_x;
if (bi_y._sign == 0) return bi_y;
if (bi_x._sign == 1 && bi_x._bits == null) return bi_y;
if (bi_x._sign == -1 && bi_x._bits == null) return bi_y.negate();
if (bi_y._sign == 1 && bi_y._bits == null) return bi_x;
if (bi_y._sign == -1 && bi_y._bits == null) return bi_x.negate();
let bits_r = new Array<number>();
BigInteger.multiplyTo(bi_x._bits, bi_y._bits, bits_r);
return BigInteger.create((bi_x._sign > 0) == (bi_y._sign > 0) ? +1 : -1, bits_r);
}
public multiply(other: number | BigInteger): BigInteger
{
return BigInteger.multiply(this, other);
}
private static multiplyTo(x: Array<number>, y: Array<number>, r: Array<number>, offset = 0): void
{
if (x.length > y.length)
{
let t = x;
x = y;
y = t;
}
for (let i = x.length + y.length - 2; i >= 0; i--)
r[i + offset] = 0;
for (let i = 0; i < x.length; i++)
{
if (x[i] == 0) continue;
for (let j = 0; j < y.length; j++)
{
let c = x[i] * y[j];
if (c == 0) continue;
let k = i + j;
do
{
c += r[k + offset] || 0;
r[k + offset] = c & DM;
c = Math.floor(c / DV);
k++;
} while (c > 0);
}
}
}
public negate(): BigInteger
{
return BigInteger.create(-this._sign, this._bits);
}
public static parse(str: string): BigInteger
{
return BigInteger.fromString(str);
}
public static pow(value: number | BigInteger, exponent: number): BigInteger
{
let bi_v = typeof value === "number" ? new BigInteger(value) : value;
if (exponent < 0 || exponent > 0x7fffffff) throw new RangeError();
if (exponent == 0) return BigInteger.One;
if (exponent == 1) return bi_v;
if (bi_v._sign == 0) return bi_v;
if (bi_v._bits.length == 1)
{
if (bi_v._bits[0] == 1) return bi_v;
if (bi_v._bits[0] == -1) return (exponent & 1) != 0 ? bi_v : BigInteger.One;
}
let h = BigInteger.bitLengthInternal(exponent);
let bi_new = BigInteger.One;
for (let i = 0; i < h; i++)
{
let e = 1 << i;
if (e > 1)
bi_v = BigInteger.multiply(bi_v, bi_v);
if ((exponent & e) != 0)
bi_new = BigInteger.multiply(bi_v, bi_new);
}
return bi_new;
}
public pow(exponent: number): BigInteger
{
return BigInteger.pow(this, exponent);
}
public static random(bitLength: number, rng?: any): BigInteger
{
if (bitLength == 0) return BigInteger.Zero;
let bytes = new Uint8Array(Math.ceil(bitLength / 8));
//if (rng == null)
{
for (let i = 0; i < bytes.length; i++)
bytes[i] = Math.random() * 256;
}
//else
//{
// rng.getRandomValues(bytes);
//}
bytes[bytes.length - 1] &= 0xff >>> (8 - bitLength % 8);
return new BigInteger(bytes);
}
public static remainder(x: number | BigInteger, y: number | BigInteger): BigInteger
{
let bi_x = typeof x === "number" ? new BigInteger(x) : x;
let bi_y = typeof y === "number" ? new BigInteger(y) : y;
return BigInteger.divRem(bi_x, bi_y).remainder;
}
public remainder(other: number | BigInteger): BigInteger
{
return BigInteger.remainder(this, other);
}
public rightShift(shift: number): BigInteger
{
if (shift == 0) return this;
let shift_units = Math.floor(shift / DB);
shift %= DB;
if (this._bits.length <= shift_units)
return BigInteger.Zero;
let bits_new = new Array<number>(this._bits.length - shift_units);
if (shift == 0)
{
for (let i = 0; i < bits_new.length; i++)
bits_new[i] = this._bits[i + shift_units];
}
else
{
for (let i = 0; i < bits_new.length; i++)
bits_new[i] = (this._bits[i + shift_units] >>> shift | this._bits[i + shift_units + 1] << (DB - shift)) & DM;
}
return BigInteger.create(this._sign, bits_new, true);
}
public sign(): number
{
return this._sign;
}
public static subtract(x: number | BigInteger, y: number | BigInteger): BigInteger
{
let bi_x = typeof x === "number" ? new BigInteger(x) : x;
let bi_y = typeof y === "number" ? new BigInteger(y) : y;
if (bi_x._sign == 0) return bi_y.negate();
if (bi_y._sign == 0) return bi_x;
if ((bi_x._sign > 0) != (bi_y._sign > 0))
return BigInteger.add(bi_x, bi_y.negate());
let c = BigInteger.compareAbs(bi_x, bi_y);
if (c == 0) return BigInteger.Zero;
if (c < 0) return BigInteger.subtract(bi_y, bi_x).negate();
let bits_r = new Array<number>();
BigInteger.subtractTo(bi_x._bits, bi_y._bits, bits_r);
return BigInteger.create(bi_x._sign, bits_r, true);
}
public subtract(other: number | BigInteger): BigInteger
{
return BigInteger.subtract(this, other);
}
private static subtractTo(x: Array<number>, y: Array<number>, r?: Array<number>): boolean
{
if (r == null) r = [];
let l = Math.min(x.length, y.length);
let c = 0, i = 0;
while (i < l)
{
c += x[i] - y[i];
r[i++] = c & DM;
c >>= DB;
}
if (x.length < y.length)
while (i < y.length)
{
c -= y[i];
r[i++] = c & DM;
c >>= DB;
}
else
while (i < x.length)
{
c += x[i];
r[i++] = c & DM;
c >>= DB;
}
return c < 0;
}
public testBit(n: number): boolean
{
let units = Math.floor(n / DB);
if (this._bits.length <= units) return false;
return (this._bits[units] & (1 << (n %= DB))) != 0;
}
public toInt32(): number
{
if (this._sign == 0) return 0;
if (this._bits.length == 1) return this._bits[0] * this._sign;
return ((this._bits[0] | this._bits[1] * DV) & 0x7fffffff) * this._sign;
}
public toString(radix = 10): string
{
if (this._sign == 0) return "0";
if (radix < 2 || radix > 36) throw new RangeError();
let s = "";
for (let bi: BigInteger = this; bi._sign != 0;)
{
let r = BigInteger.divRem(bi, radix);
let rem = Math.abs(r.remainder.toInt32());
if (rem < 10) rem += 0x30;
else rem += 0x57;
s = String.fromCharCode(rem) + s;
bi = r.result;
}
if (this._sign < 0) s = "-" + s;
return s;
}
public toUint8Array(littleEndian = true, length?: number): Uint8Array
{
if (this._sign == 0) return new Uint8Array(length || 1);
let cb = Math.ceil((this._bits.length * DB + 1) / 8);
let array = new Uint8Array(length || cb);
for (let i = 0; i < array.length; i++)
{
let offset = littleEndian ? i : array.length - 1 - i;
let cbits = i * 8;
let cu = Math.floor(cbits / DB);
cbits %= DB;
if (DB - cbits < 8)
array[offset] = (this._bits[cu] >>> cbits | this._bits[cu + 1] << (DB - cbits)) & 0xff;
else
array[offset] = this._bits[cu] >>> cbits & 0xff;
}
length = length || BigInteger.getActualLength(array);
if (length < array.length)
array = array.subarray(0, length);
return array;
}
public toUint8ArrayWithSign(littleEndian = true, length?: number): Uint8Array
{
if (this._sign == 0) return new Uint8Array(length || 1);
if (this._sign > 0)
{//正数
let cb = Math.ceil((this._bits.length * DB + 1) / 8);
let array = new Uint8Array(length || cb);
for (let i = 0; i < array.length; i++)
{
let offset = littleEndian ? i : array.length - 1 - i;
let cbits = i * 8;
let cu = Math.floor(cbits / DB);
if (cu <= this._bits.length)
{
cbits %= DB;
if (DB - cbits < 8)
array[offset] = (this._bits[cu] >>> cbits | this._bits[cu + 1] << (DB - cbits)) & 0xff;
else
array[offset] = this._bits[cu] >>> cbits & 0xff;
}
else
{
array[offset] = 0;
}
}
length = length || BigInteger.getActualLength(array);
if (length < array.length)
array = array.subarray(0, length);
if ((array[array.length - 1] & 0x80) > 0)//最高位为负数
{
var newarr = new Uint8Array(array.length + 1);
for (var i = 0; i < array.length; i++)
{
newarr[i] = array[i];
}
newarr[array.length] = 0;
array = newarr;
}
return array;
}
else
{//负数
//+1 改符号取数据
var n = this.add(1);
if (n.sign() < 0)
n["_sign"] = 1;
var array = n.toUint8Array();
var needaddsign = (array[array.length - 1] & 0x80) > 0;//最高位为1,翻转后是0,需要特殊处理
var newarr = new Uint8Array(needaddsign ? array.length + 1 : array.length);
//全部取反
for (var i = 0; i < array.length; i++)
{
newarr[i] = ~array[i];
}
if (needaddsign)
{
newarr[i] = 0xff;
}
array = newarr;
return array;
}
}
}
}