UNPKG

blocktrail-sdk

Version:

BlockTrail's Developer Friendly API binding for NodeJS

454 lines (341 loc) 12.4 kB
function is_big_number ( a ) { return ( a instanceof BigNumber ); } /////////////////////////////////////////////////////////////////////////////// var _bigint_heap = new Uint32Array(0x100000), _bigint_asm = bigint_asm( global, null, _bigint_heap.buffer ); /////////////////////////////////////////////////////////////////////////////// var _BigNumber_ZERO_limbs = new Uint32Array(0); function BigNumber ( num ) { var limbs = _BigNumber_ZERO_limbs, bitlen = 0, sign = 0; if ( is_string(num) ) num = string_to_bytes(num); if ( is_buffer(num) ) num = new Uint8Array(num); if ( num === undefined ) { // do nothing } else if ( is_number(num) ) { var absnum = Math.abs(num); if ( absnum > 0xffffffff ) { limbs = new Uint32Array(2); limbs[0] = absnum|0; limbs[1] = (absnum/0x100000000)|0; bitlen = 52; } else if ( absnum > 0 ) { limbs = new Uint32Array(1); limbs[0] = absnum; bitlen = 32; } else { limbs = _BigNumber_ZERO_limbs; bitlen = 0; } sign = num < 0 ? -1 : 1; } else if ( is_bytes(num) ) { for ( var i = 0; !num[i]; i++ ); bitlen = ( num.length - i ) * 8; if ( !bitlen ) return BigNumber_ZERO; limbs = new Uint32Array( (bitlen + 31) >> 5 ); for ( var j = num.length-4; j >= i ; j -= 4 ) { limbs[(num.length-4-j)>>2] = (num[j] << 24) | (num[j+1] << 16) | (num[j+2] << 8) | num[j+3]; } if ( i-j === 3 ) { limbs[limbs.length-1] = num[i]; } else if ( i-j === 2 ) { limbs[limbs.length-1] = (num[i] << 8) | num[i+1]; } else if ( i-j === 1 ) { limbs[limbs.length-1] = (num[i] << 16) | (num[i+1] << 8) | num[i+2]; } sign = 1; } else if ( typeof num === 'object' && num !== null ) { limbs = new Uint32Array( num.limbs ); bitlen = num.bitLength; sign = num.sign; } else { throw new TypeError("number is of unexpected type"); } this.limbs = limbs; this.bitLength = bitlen; this.sign = sign; } function BigNumber_toString ( radix ) { radix = radix || 16; var limbs = this.limbs, bitlen = this.bitLength, str = ''; if ( radix === 16 ) { // FIXME clamp last limb to (bitlen % 32) for ( var i = (bitlen+31>>5)-1; i >= 0; i-- ) { var h = limbs[i].toString(16); str += '00000000'.substr(h.length); str += h; } str = str.replace( /^0+/, '' ); if ( !str.length ) str = '0'; } else { throw new IllegalArgumentError("bad radix"); } if ( this.sign < 0 ) str = '-' + str; return str; } function BigNumber_toBytes () { var bitlen = this.bitLength, limbs = this.limbs; if ( bitlen === 0 ) return new Uint8Array(0); var bytelen = ( bitlen + 7 ) >> 3, bytes = new Uint8Array(bytelen); for ( var i = 0; i < bytelen; i++ ) { var j = bytelen - i - 1; bytes[i] = limbs[j>>2] >> ( (j & 3) << 3 ); } return bytes; } // Downgrade to Number function BigNumber_valueOf () { var limbs = this.limbs, bits = this.bitLength, sign = this.sign; if ( !sign ) return 0; if ( bits <= 32 ) return sign * (limbs[0]>>>0); if ( bits <= 52 ) return sign * ( 0x100000000 * (limbs[1]>>>0) + (limbs[0]>>>0) ); // normalization var i, l, e = 0; for ( i = limbs.length-1; i >= 0; i-- ) { if ( (l = limbs[i]) === 0 ) continue; while ( ( (l << e) & 0x80000000 ) === 0 ) e++; break; } if ( i === 0 ) return sign * (limbs[0]>>>0); return sign * ( 0x100000 * (( (limbs[i] << e) | ( e ? limbs[i-1] >>> (32-e) : 0 ) )>>>0) + (( (limbs[i-1] << e) | ( e && i > 1 ? limbs[i-2] >>> (32-e) : 0 ) )>>>12) ) * Math.pow( 2, 32*i-e-52 ); } function BigNumber_clamp ( b ) { var limbs = this.limbs, bitlen = this.bitLength; // FIXME check b is number and in a valid range if ( b >= bitlen ) return this; var clamped = new BigNumber, n = (b + 31) >> 5, k = b % 32; clamped.limbs = new Uint32Array( limbs.subarray(0,n) ); clamped.bitLength = b; clamped.sign = this.sign; if ( k ) clamped.limbs[n-1] &= (-1 >>> (32-k)); return clamped; } function BigNumber_slice ( f, b ) { if ( !is_number(f) ) throw new TypeError("TODO"); if ( b !== undefined && !is_number(b) ) throw new TypeError("TODO"); var limbs = this.limbs, bitlen = this.bitLength; if ( f < 0 ) throw new RangeError("TODO"); if ( f >= bitlen ) return BigNumber_ZERO; if ( b === undefined || b > bitlen - f ) b = bitlen - f; var sliced = new BigNumber, slimbs, n = f >> 5, m = (f + b + 31) >> 5, l = (b + 31) >> 5, t = f % 32, k = b % 32; slimbs = new Uint32Array(l); if ( t ) { for ( var i = 0; i < m-n-1; i++ ) { slimbs[i] = (limbs[n+i]>>>t) | ( limbs[n+i+1]<<(32-t) ); } slimbs[i] = limbs[n+i]>>>t; } else { slimbs.set( limbs.subarray(n, m) ); } if ( k ) { slimbs[l-1] &= (-1 >>> (32-k)); } sliced.limbs = slimbs sliced.bitLength = b; sliced.sign = this.sign; return sliced; } /////////////////////////////////////////////////////////////////////////////// function BigNumber_negate () { var negative = new BigNumber; negative.limbs = this.limbs; negative.bitLength = this.bitLength; negative.sign = -1 * this.sign; return negative; } function BigNumber_compare ( that ) { if ( !is_big_number(that) ) that = new BigNumber(that); var alimbs = this.limbs, alimbcnt = alimbs.length, blimbs = that.limbs, blimbcnt = blimbs.length, z = 0; if ( this.sign < that.sign ) return -1; if ( this.sign > that.sign ) return 1; _bigint_heap.set( alimbs, 0 ); _bigint_heap.set( blimbs, alimbcnt ); z = _bigint_asm.cmp( 0, alimbcnt<<2, alimbcnt<<2, blimbcnt<<2 ); return z * this.sign; } function BigNumber_add ( that ) { if ( !is_big_number(that) ) that = new BigNumber(that); if ( !this.sign ) return that; if ( !that.sign ) return this; var abitlen = this.bitLength, alimbs = this.limbs, alimbcnt = alimbs.length, asign = this.sign, bbitlen = that.bitLength, blimbs = that.limbs, blimbcnt = blimbs.length, bsign = that.sign, rbitlen, rlimbcnt, rsign, rof, result = new BigNumber; rbitlen = ( abitlen > bbitlen ? abitlen : bbitlen ) + ( asign * bsign > 0 ? 1 : 0 ); rlimbcnt = ( rbitlen + 31 ) >> 5; _bigint_asm.sreset(); var pA = _bigint_asm.salloc( alimbcnt<<2 ), pB = _bigint_asm.salloc( blimbcnt<<2 ), pR = _bigint_asm.salloc( rlimbcnt<<2 ); _bigint_asm.z( pR-pA+(rlimbcnt<<2), 0, pA ); _bigint_heap.set( alimbs, pA>>2 ); _bigint_heap.set( blimbs, pB>>2 ); if ( asign * bsign > 0 ) { _bigint_asm.add( pA, alimbcnt<<2, pB, blimbcnt<<2, pR, rlimbcnt<<2 ); rsign = asign; } else if ( asign > bsign ) { rof = _bigint_asm.sub( pA, alimbcnt<<2, pB, blimbcnt<<2, pR, rlimbcnt<<2 ); rsign = rof ? bsign : asign; } else { rof = _bigint_asm.sub( pB, blimbcnt<<2, pA, alimbcnt<<2, pR, rlimbcnt<<2 ); rsign = rof ? asign : bsign; } if ( rof ) _bigint_asm.neg( pR, rlimbcnt<<2, pR, rlimbcnt<<2 ); if ( _bigint_asm.tst( pR, rlimbcnt<<2 ) === 0 ) return BigNumber_ZERO; result.limbs = new Uint32Array( _bigint_heap.subarray( pR>>2, (pR>>2)+rlimbcnt ) ); result.bitLength = rbitlen; result.sign = rsign; return result; } function BigNumber_subtract ( that ) { if ( !is_big_number(that) ) that = new BigNumber(that); return this.add( that.negate() ); } function BigNumber_multiply ( that ) { if ( !is_big_number(that) ) that = new BigNumber(that); if ( !this.sign || !that.sign ) return BigNumber_ZERO; var abitlen = this.bitLength, alimbs = this.limbs, alimbcnt = alimbs.length, bbitlen = that.bitLength, blimbs = that.limbs, blimbcnt = blimbs.length, rbitlen, rlimbcnt, result = new BigNumber; rbitlen = abitlen + bbitlen; rlimbcnt = ( rbitlen + 31 ) >> 5; _bigint_asm.sreset(); var pA = _bigint_asm.salloc( alimbcnt<<2 ), pB = _bigint_asm.salloc( blimbcnt<<2 ), pR = _bigint_asm.salloc( rlimbcnt<<2 ); _bigint_asm.z( pR-pA+(rlimbcnt<<2), 0, pA ); _bigint_heap.set( alimbs, pA>>2 ); _bigint_heap.set( blimbs, pB>>2 ); _bigint_asm.mul( pA, alimbcnt<<2, pB, blimbcnt<<2, pR, rlimbcnt<<2 ); result.limbs = new Uint32Array( _bigint_heap.subarray( pR>>2, (pR>>2)+rlimbcnt ) ); result.sign = this.sign * that.sign; result.bitLength = rbitlen; return result; } function BigNumber_square () { if ( !this.sign ) return BigNumber_ZERO; var abitlen = this.bitLength, alimbs = this.limbs, alimbcnt = alimbs.length, rbitlen, rlimbcnt, result = new BigNumber; rbitlen = abitlen << 1; rlimbcnt = ( rbitlen + 31 ) >> 5; _bigint_asm.sreset(); var pA = _bigint_asm.salloc( alimbcnt<<2 ), pR = _bigint_asm.salloc( rlimbcnt<<2 ); _bigint_asm.z( pR-pA+(rlimbcnt<<2), 0, pA ); _bigint_heap.set( alimbs, pA>>2 ); _bigint_asm.sqr( pA, alimbcnt<<2, pR ); result.limbs = new Uint32Array( _bigint_heap.subarray( pR>>2, (pR>>2)+rlimbcnt ) ); result.bitLength = rbitlen; result.sign = 1; return result; } function BigNumber_divide ( that ) { if ( !is_big_number(that) ) that = new BigNumber(that); var abitlen = this.bitLength, alimbs = this.limbs, alimbcnt = alimbs.length, bbitlen = that.bitLength, blimbs = that.limbs, blimbcnt = blimbs.length, qlimbcnt, rlimbcnt, quotient = BigNumber_ZERO, remainder = BigNumber_ZERO; _bigint_asm.sreset(); var pA = _bigint_asm.salloc( alimbcnt<<2 ), pB = _bigint_asm.salloc( blimbcnt<<2 ), pQ = _bigint_asm.salloc( alimbcnt<<2 ); _bigint_asm.z( pQ-pA+(alimbcnt<<2), 0, pA ); _bigint_heap.set( alimbs, pA>>2 ); _bigint_heap.set( blimbs, pB>>2 ); _bigint_asm.div( pA, alimbcnt<<2, pB, blimbcnt<<2, pQ ); qlimbcnt = _bigint_asm.tst( pQ, alimbcnt<<2 )>>2; if ( qlimbcnt ) { quotient = new BigNumber; quotient.limbs = new Uint32Array( _bigint_heap.subarray( pQ>>2, (pQ>>2)+qlimbcnt ) ); quotient.bitLength = abitlen < (qlimbcnt<<5) ? abitlen : (qlimbcnt<<5); quotient.sign = this.sign * that.sign; } rlimbcnt = _bigint_asm.tst( pA, blimbcnt<<2 )>>2; if ( rlimbcnt ) { remainder = new BigNumber; remainder.limbs = new Uint32Array( _bigint_heap.subarray( pA>>2, (pA>>2)+rlimbcnt ) );; remainder.bitLength = bbitlen < (rlimbcnt<<5) ? bbitlen : (rlimbcnt<<5); remainder.sign = this.sign; } return { quotient: quotient, remainder: remainder }; } /////////////////////////////////////////////////////////////////////////////// var BigNumberPrototype = BigNumber.prototype = new Number; BigNumberPrototype.toString = BigNumber_toString; BigNumberPrototype.toBytes = BigNumber_toBytes; BigNumberPrototype.valueOf = BigNumber_valueOf; BigNumberPrototype.clamp = BigNumber_clamp; BigNumberPrototype.slice = BigNumber_slice; /////////////////////////////////////////////////////////////////////////////// BigNumberPrototype.negate = BigNumber_negate; BigNumberPrototype.compare = BigNumber_compare; BigNumberPrototype.add = BigNumber_add; BigNumberPrototype.subtract = BigNumber_subtract; BigNumberPrototype.multiply = BigNumber_multiply; BigNumberPrototype.square = BigNumber_square; BigNumberPrototype.divide = BigNumber_divide; /////////////////////////////////////////////////////////////////////////////// var BigNumber_ZERO = new BigNumber(0), BigNumber_ONE = new BigNumber(1); Object.freeze(BigNumber_ZERO); Object.freeze(BigNumber_ONE);