Comparing version 0.2.31 to 0.2.40
@@ -0,1 +1,2 @@ | ||
import { u128 } from '../integer/u128'; | ||
import { u256 } from '../integer/u256'; | ||
@@ -351,2 +352,92 @@ | ||
}); | ||
it("Should multiply two u256 numbers", () => { | ||
var a = u256.from(3); | ||
var b = u256.from(3); | ||
var r = u256.from(9); | ||
expect(a * b).toStrictEqual(r); | ||
expect(b * a).toStrictEqual(r); | ||
}); | ||
it("Should multiply two u256 numbers", () => { | ||
var a = u256.from(43545453452); | ||
var b = u256.from(2353454354); | ||
var r = new u256(10248516654965971928, 5); | ||
expect(a * b).toStrictEqual(r); | ||
expect(b * a).toStrictEqual(r); | ||
}); | ||
it("Should multiply two u256 numbers - 2", () => { | ||
var a = u256.from(11); | ||
var b = new u256(0, 2); | ||
var r = new u256(0, 22); | ||
expect(a * b).toStrictEqual(r); | ||
expect(b * a).toStrictEqual(r); | ||
}); | ||
it("Should multiply two u256 numbers - 3", () => { | ||
var a = new u256(0, 3); | ||
var b = new u256(0, 0,3); | ||
var r = new u256(0, 0,0,9); | ||
expect(a * b).toStrictEqual(r); | ||
expect(b * a).toStrictEqual(r); | ||
}); | ||
it("Should multiply two u256 numbers - 4", () => { | ||
var a = u256.from(new u128(14083847773837265618, 6692605942)); | ||
var b = u256.from(new u128(18444665141527514289, 5354084802)); | ||
var r = new u256(5659639222556316466, 4474720309748468391, 17386035696907167262, 1); | ||
expect(a * b).toStrictEqual(r); | ||
expect(b * a).toStrictEqual(r); | ||
}); | ||
it("Should multiply u256 numbers by 1", () => { | ||
var a = u256.Max; | ||
var b = u256.One; | ||
var r = a; | ||
expect(a * b).toStrictEqual(r); | ||
expect(b * a).toStrictEqual(r); | ||
}); | ||
it("Should multiply u256 numbers by 0", () => { | ||
var a = new u256(5656466, 447478468391, 17386907167262, 1); | ||
var b = u256.Zero; | ||
var r = b; | ||
expect(a * b).toStrictEqual(r); | ||
expect(b * a).toStrictEqual(r); | ||
}); | ||
it("Should multiply two u256 numbers with overflow", () => { | ||
var a = new u256(0, 0, 1); | ||
expect(a * a).toStrictEqual(u256.Zero); | ||
}); | ||
it("Should multiply two u256 numbers with overflow - 2", () => { | ||
var a = new u256(1, 0, 1); | ||
expect(a * a).toStrictEqual(new u256(1, 0, 2)); | ||
}); | ||
it("Should multiply two u256 numbers with overflow - 3", () => { | ||
var a = new u256(6, 0, 0, 420); | ||
var b = new u256(0, 7, 0, 0); | ||
var r = new u256(0, 42, 0, 0); | ||
expect(a * b).toStrictEqual(r); | ||
expect(b * a).toStrictEqual(r); | ||
}); | ||
it("Should multiply two u256 numbers with overflow - 3", () => { | ||
var a = new u256(2, 666, 666, 666); | ||
var b = new u256(0, 0, 0, 3); | ||
var r = new u256(0, 0, 0, 6); | ||
expect(a * b).toStrictEqual(r); | ||
expect(b * a).toStrictEqual(r); | ||
}); | ||
}); |
@@ -0,1 +1,2 @@ | ||
import { u256 } from './integer'; | ||
import { u128 } from './integer/u128'; | ||
@@ -10,2 +11,4 @@ | ||
@lazy export var __res128_hi: u64 = 0; | ||
// used for returning 0 or 1 | ||
@lazy export var __carry: u64 = 0; | ||
@@ -79,5 +82,5 @@ /** | ||
var w0 = uv & 0xFFFFFFFF; | ||
uv = a * v + (uv >> 32); | ||
uv = a * v + (uv >> 32); | ||
var w1 = uv >> 32; | ||
uv = u * b + (uv & 0xFFFFFFFF); | ||
uv = u * b + (uv & 0xFFFFFFFF); | ||
@@ -88,4 +91,64 @@ __res128_hi = a * b + w1 + (uv >> 32); | ||
// __umul64Hop computes (hi * 2^64 + lo) = z + (x * y) | ||
// @ts-ignore: decorator | ||
@inline | ||
export function __umul64Hop(z: u64, x: u64, y: u64): u64 { | ||
var lo = __umulq64(x, y); | ||
lo = __uadd64(lo, z); | ||
var hi = __res128_hi +__carry; | ||
__res128_hi = hi; | ||
return lo | ||
} | ||
// __umul64Step computes (hi * 2^64 + lo) = z + (x * y) + carry. | ||
// @ts-ignore: decorator | ||
@inline | ||
export function __umul64Step(z: u64, x: u64, y: u64, carry: u64): u64 { | ||
var lo = __umulq64(x, y) | ||
lo = __uadd64(lo, carry); | ||
var hi = __uadd64(__res128_hi, 0, __carry); | ||
lo = __uadd64(lo, z); | ||
hi += __carry; | ||
__res128_hi = hi; | ||
return lo | ||
} | ||
// __uadd64 returns the sum with carry of x, y and carry: sum = x + y + carry. | ||
// The carry input must be 0 or 1; otherwise the behavior is undefined. | ||
// The carryOut output is guaranteed to be 0 or 1. | ||
// @ts-ignore: decorator | ||
@inline | ||
export function __uadd64(x: u64, y: u64, carry: u64 = 0): u64 { | ||
var sum = x + y + carry | ||
// // The sum will overflow if both top bits are set (x & y) or if one of them | ||
// // is (x | y), and a carry from the lower place happened. If such a carry | ||
// // happens, the top bit will be 1 + 0 + 1 = 0 (& ~sum). | ||
__carry = ((x & y) | ((x | y) & ~sum)) >>> 63 | ||
return sum; | ||
} | ||
// u256 * u256 => u256 implemented from https://github.com/holiman/uint256 | ||
// @ts-ignore: decorator | ||
@global | ||
export function __mul256(x0: u64, x1: u64, x2: u64, x3: u64, y0: u64, y1: u64, y2: u64, y3: u64): u256 { | ||
var lo1 = __umulq64(x0, y0); | ||
var res1 = __umul64Hop(__res128_hi, x1, y0); | ||
var res2 = __umul64Hop(__res128_hi, x2, y0); | ||
var res3 = x3 * y0 + __res128_hi; | ||
var lo2 = __umul64Hop(res1, x0, y1); | ||
res2 = __umul64Step(res2, x1, y1, __res128_hi); | ||
res3 += x2 * y1 + __res128_hi; | ||
var hi1 = __umul64Hop(res2, x0, y2); | ||
res3 += x1 * y2 + __res128_hi | ||
var hi2 = __umul64Hop(res3, x0, y3); | ||
return new u256(lo1, lo2, hi1, hi2); | ||
} | ||
// @ts-ignore: decorator | ||
@global | ||
export function __multi3(al: u64, ah: u64, bl: u64, bh: u64): u64 { | ||
@@ -92,0 +155,0 @@ var u = al, v = bl; |
@@ -239,3 +239,3 @@ import { u256Safe as u256 } from './u256'; | ||
static sub(a: u128, b: u128): u128 { | ||
if (a < b) throw new RangeError("Underflow during substraction"); | ||
if (a < b) throw new RangeError("Underflow during subtraction"); | ||
return changetype<u128>( | ||
@@ -242,0 +242,0 @@ U128.sub(changetype<U128>(a), changetype<U128>(b)) |
import { i128 } from './i128'; | ||
import { u128 } from './u128'; | ||
import { u256toDecimalString } from "../utils"; | ||
import { __mul256 } from '../globals'; | ||
@@ -144,2 +145,27 @@ @lazy const HEX_CHARS = '0123456789abcdef'; | ||
/** | ||
* Create 256-bit unsigned integer from generic type T | ||
* @param value | ||
* @returns 256-bit unsigned integer | ||
*/ | ||
@inline | ||
static from<T>(value: T): u256 { | ||
if (value instanceof bool) return u256.fromU64(<u64>value); | ||
else if (value instanceof i8) return u256.fromI64(<i64>value); | ||
else if (value instanceof u8) return u256.fromU64(<u64>value); | ||
else if (value instanceof i16) return u256.fromI64(<i64>value); | ||
else if (value instanceof u16) return u256.fromU64(<u64>value); | ||
else if (value instanceof i32) return u256.fromI64(<i64>value); | ||
else if (value instanceof u32) return u256.fromU64(<u64>value); | ||
else if (value instanceof i64) return u256.fromI64(<i64>value); | ||
else if (value instanceof u64) return u256.fromU64(<u64>value); | ||
else if (value instanceof f32) return u256.fromF64(<f64>value); | ||
else if (value instanceof f64) return u256.fromF64(<f64>value); | ||
else if (value instanceof u128) return u256.fromU128(<u128>value); | ||
else if (value instanceof u256) return u256.fromU256(<u256>value); | ||
else if (value instanceof u8[]) return u256.fromBytes(<u8[]>value); | ||
else if (value instanceof Uint8Array) return u256.fromBytes(<Uint8Array>value); | ||
else throw new TypeError("Unsupported generic type"); | ||
} | ||
// TODO | ||
@@ -435,2 +461,8 @@ // static fromString(str: string): u256 | ||
// mul: u256 x u256 = u256 | ||
@inline @operator('*') | ||
static mul(a: u256, b: u256): u256 { | ||
return __mul256(a.lo1, a.lo2, a.hi1, a.hi2, b.lo1, b.lo2, b.hi1, b.hi2) | ||
} | ||
@inline | ||
@@ -437,0 +469,0 @@ static popcnt(value: u256): i32 { |
{ | ||
"name": "as-bignum", | ||
"version": "0.2.31", | ||
"version": "0.2.40", | ||
"description": "128 and 256 bits integer and fixed point arithmetics for AssemblyScript. Also support checking overflow/underflow", | ||
@@ -37,3 +37,3 @@ "main": "assembly/index.ts", | ||
"assemblyscript": "^0.27.2", | ||
"typescript": "^5.0.4" | ||
"typescript": "^5.1" | ||
}, | ||
@@ -40,0 +40,0 @@ "files": [ |
Sorry, the diff of this file is not supported yet
329572
4739