UNPKG

as-soroban-sdk

Version:

AssemblyScript SDK for writing contracts for Soroban.

772 lines (712 loc) 28.9 kB
// Offers arithmetic helper functions for I128Val and U128Val host values. // Uses u256 and i256 host functions to make the calculations. // Supports positive and negative values import { Bytes } from "./bytes"; import * as context from "./context"; import { i256_add, i256_div, i256_mul, i256_pow, i256_rem_euclid, i256_shl, i256_shr, i256_sub, i256_val_from_be_bytes, i256_val_to_be_bytes, obj_cmp, u256_add, u256_div, u256_mul, u256_pow, u256_rem_euclid, u256_shl, u256_shr } from "./env"; import { BytesObject, I128Object, I128Val, I256Val, U128Val, U256Val, U32Val, Val, errorCodeArithDomain, errorTypeObject, fromError, fromI128Pieces, fromI128Small, fromI256Pieces, fromI256Small,fromU128Pieces, fromU128Small, fromU256Pieces, fromU256Small, isError, isI128Object, isI128Small, isI256Object, isI256Small, isU128Object, isU128Small, isU256Object, isU256Small, toI128High64, toI128Low64, toI128Small, toI256HiHi, toI256HiLo, toI256LoHi, toI256LoLo, toI256Small, toU128High64, toU128Low64, toU128Small, toU256HiHi, toU256HiLo, toU256LoHi, toU256LoLo, toU256Small} from "./value"; /***************** Unsigned U128 *****************/ /** * Performs checked unsigned integer addition. Computes `lhs + rhs`. * Uses the u256_add host function to perform the addition. * @param lhs U128Val left value to add * @param rhs U128Val right value to add * @returns U128Val or `Error` (errorTypeObject, errorCodeArithDomain) if overflow occurred. */ export function u128Add(lhs:U128Val, rhs:U128Val) : Val { let a256 = getU256FromU128(lhs); let b256 = getU256FromU128(rhs); let ru256 = u256_add(a256, b256); return getU128FromU256(ru256); } /** * Performs unsigned integer addition. Computes `lhs + rhs`. * Uses the u256_add host function to perform the addition. * @param lhs U128Val left value to add * @param rhs U128Val right value to add * @returns U256Val (U256Small or U256Object) so that no overflow can occur. */ export function u128AddToU256(lhs:U128Val, rhs:U128Val) : U256Val { let a256 = getU256FromU128(lhs); let b256 = getU256FromU128(rhs); return u256_add(a256, b256); } /** * Performs checked unsigned integer subtraction. Computes `lhs - rhs`. * Uses the i256_sub host function to perform the subtraction. * @param lhs U128Val value to substract from * @param rhs U128Val value to be substracted * @returns U128Val or `Error` (errorTypeObject, errorCodeArithDomain) if underflow occurred (result < 0). */ export function u128Sub(lhs:U128Val, rhs:U128Val) : Val { let a256 = getI256FromU128(lhs); let b256 = getI256FromU128(rhs); let ri256 = i256_sub(a256, b256); return getU128FromI256(ri256); } /** * Performs unsigned integer subtraction. Computes `lhs - rhs`. * Uses the i256_sub host function to perform the subtraction. * @param lhs U128Val value to substract from * @param rhs U128Val value to be substracted * @returns I256Val (I256Small or I256Object) so that no underflow can occur. */ export function u128SubToI256(lhs:U128Val, rhs:U128Val) : I256Val { let a256 = getI256FromU128(lhs); let b256 = getI256FromU128(rhs); return i256_sub(a256, b256); } /** * Performs checked unsigned integer multiplication. Computes `lhs * rhs`. * Uses the u256_mul host function to perform the multiplication. * @param lhs U128Val left value to be multiplied * @param rhs U128Val right value to be multiplied * @returns U128Val or `Error` (errorTypeObject, errorCodeArithDomain) if overflow occurred. */ export function u128Mul(lhs:U128Val, rhs:U128Val) : Val { let a256 = getU256FromU128(lhs); let b256 = getU256FromU128(rhs); let ru256 = u256_mul(a256, b256); return getU128FromU256(ru256); } /** * Performs unsigned integer multiplication. Computes `lhs * rhs`. * Uses the u256_mul host function to perform the multiplication. * @param lhs U128Val left value to be multiplied * @param rhs U128Val right value to be multiplied * @returns U256Val (U256Small or U256Object) so that no overflow can occur. */ export function u128MulToU256(lhs:U128Val, rhs:U128Val) : U256Val { let a256 = getU256FromU128(lhs); let b256 = getU256FromU128(rhs); return u256_mul(a256, b256); } /** * Performs checked unsigned integer division. Computes `lhs / rhs`. * Uses the u256_div host function to perform the division. * @param lhs U128Val value to be devided * @param rhs U128Val value to devide by * @returns U128Val or `Error` (errorTypeObject, errorCodeArithDomain) if rhs == 0. */ export function u128Div(lhs:U128Val, rhs:U128Val) : Val { let b256 = getU256FromU128OrErrorIfZero(rhs); if (isError(b256)) { return b256; } let a256 = getU256FromU128(lhs); let ru256 = u256_div(a256, b256); return getU128FromU256(ru256); } /** * Multiplies and devides u128 numbers without overflow in multiplication part (number * numerator / denominator). * Traps if not U128Val (U128Object or U128SmallVal) values. * @param number number to multiply with numerator U128Val. * @param numerator numerator to be multiplied with number U128Val. * @param denominator denominator U128Val. * @returns U128Val as the result of number * numerator / denominator or `Error` (errorTypeObject, errorCodeArithDomain) on overflow. */ export function u128MulDiv(number:U128Val, numerator:U128Val, denominator: U128Val) : Val { let number256 = getU256FromU128(number); let numerator256 = getU256FromU128(numerator); let denominator256 = getU256FromU128OrErrorIfZero(denominator); let ru256 = u256_div(u256_mul(number256, numerator256), denominator256); return getU128FromU256(ru256); } /** * Multiplies and devides u128 numbers without overflow in multiplication part (number * numerator / denominator). * Traps if not U128Val (U128Object or U128SmallVal) values. * @param number number to multiply with numerator U128Val. * @param numerator numerator to be multiplied with number U128Val. * @param denominator denominator U128Val. * @returns U256Val as the result of number * numerator / denominator or `Error` (errorTypeObject, errorCodeArithDomain) on overflow. */ export function u128MulDivToU256(number:U128Val, numerator:U128Val, denominator: U128Val) : U256Val { let number256 = getU256FromU128(number); let numerator256 = getU256FromU128(numerator); let denominator256 = getU256FromU128OrErrorIfZero(denominator); return u256_div(u256_mul(number256, numerator256), denominator256); } /** * Performs checked unsigned integer Euclidean modulo. Computes `lhs % rhs`. * Uses the u256_rem_euclid host function to perform the modulo. * @param lhs U128Val left value * @param rhs U128Val right value * @returns U128Val or `Error` (errorTypeObject, errorCodeArithDomain) if rhs == 0. */ export function u128RemEuclid(lhs:U128Val, rhs:U128Val) : Val { let b256 = getU256FromU128OrErrorIfZero(rhs); if (isError(b256)) { return b256; } let a256 = getU256FromU128(lhs); let ru256 = u256_rem_euclid(a256, b256); return getU128FromU256(ru256); } /** * Performs checked unsigned integer exponentiation. Computes `lhs.exp(rhs)` * Uses the u256_pow host function to perform the exponentiation. * @param lhs U128Val left value (base) * @param rhs U128Val right value (exponent) * @returns U128Val or `Error` (errorTypeObject, errorCodeArithDomain) if overflow occurred. */ export function u128Pow(lhs:U128Val, rhs:U32Val) : Val { let a256 = getU256FromU128(lhs); let ru256 = u256_pow(a256, rhs); return getU128FromU256(ru256); } /** * Performs unsigned integer exponentiation. Computes `lhs.exp(rhs)`. * Uses the u256_pow host function to perform the exponentiation. * @param lhs U128Val left value (base) * @param rhs U128Val right value (exponent) * @returns U256Val (U256Small or U256Object). Traps if u256 overflow occurs. */ export function u128PowToU256(lhs:U128Val, rhs:U32Val) : U256Val { let a256 = getU256FromU128(lhs); return u256_pow(a256, rhs); } // Performs checked unsigned integer shift left. Computes `lhs << rhs`, // returning U128Val or `Error` (errorTypeObject, errorCodeArithDomain) if overflow occurred. // Uses the u256_shl host function to perform the shift left. // Traps if u256_shl error occurs (if `rhs` is larger than or equal to the number of bits in `lhs`) /** * Performs checked unsigned integer shift left. Computes `lhs << rhs`. * Uses the u256_shl host function to perform the shift left. * Traps if u256_shl error occurs (if `rhs` is larger than or equal to the number of bits in `lhs`) * @param lhs U128Val value to shift left * @param rhs U32Val shift left by this value * @returns U128Val or `Error` (errorTypeObject, errorCodeArithDomain) if overflow occurred. */ export function u128Shl(lhs:U128Val, rhs:U32Val) : Val { let a256 = getU256FromU128(lhs); let ru256 = u256_shl(a256, rhs); return getU128FromU256(ru256); } /** * Performs unsigned integer shift left. Computes `lhs << rhs`. * Uses the u256_shl host function to perform the shift left. * Traps if u256_shl error occurs (if `rhs` is larger than or equal to the number of bits in `lhs`) * @param lhs U128Val value to shift left * @param rhs U32Val shift left by this value * @returns U256Val (U256Small or U256Object). Traps if u256 overflow occurs. */ export function u128ShlToU256(lhs:U128Val, rhs:U32Val) : Val { let a256 = getU256FromU128(lhs); return u256_shl(a256, rhs); } /** * Performs checked unsigned integer shift right. Computes `lhs >> rhs`. * Uses the u256_shr host function to perform the shift right. * Traps if u256_shr error occurs (if `rhs` is larger than or equal to the number of bits in `lhs`) * @param lhs U128Val value to shift right * @param rhs U32Val shift right by this value * @returns U128Val (U128Small or U128Object). */ export function u128Shr(lhs:U128Val, rhs:U32Val) : Val { let a256 = getU256FromU128(lhs); let ru256 = u256_shr(a256, rhs); return getU128FromU256(ru256); } /** * Performs unsigned integer shift right. Computes `lhs >> rhs`. * Uses the u256_shr host function to perform the shift right. * Traps if u256_shr error occurs (if `rhs` is larger than or equal to the number of bits in `lhs`) * @param lhs U128Val value to shift right * @param rhs U32Val shift right by this value * @returns U256Val (U256Small or U256Object). */ export function u128ShrToU256(lhs:U128Val, rhs:U32Val) : Val { let a256 = getU256FromU128(lhs); return u256_shr(a256, rhs); } /******************************************************************** Signed I128 positive and negative ********************************************************************/ /** * Performs checked signed integer addition. Computes `lhs + rhs`. * Uses the i256_add host function to perform the addition. * @param lhs I256Val left value to add * @param rhs I256Val right value to add * @returns I128Val or `Error` (errorTypeObject, errorCodeArithDomain) if overflow occurred. */ export function i128Add(lhs:I128Val, rhs:I128Val) : Val { let a256 = getI256FromI128(lhs); let b256 = getI256FromI128(rhs); let ru256 = i256_add(a256, b256); return getI128FromI256(ru256); } /** * Performs signed integer addition. Computes `lhs + rhs`. * Uses the i256_add host function to perform the addition. * @param lhs I256Val left value to add * @param rhs I256Val right value to add * @returns I256Val (I256Small or I256Object) so that no overflow can occur. */ export function i128AddToI256(lhs:I128Val, rhs:I128Val) : I256Val { let a256 = getI256FromI128(lhs); let b256 = getI256FromI128(rhs); return i256_add(a256, b256); } /** * Performs checked signed integer subtraction. Computes `lhs - rhs`. * Uses the i256_sub host function to perform the subtraction. * @param lhs I256Val value to substract from * @param rhs I256Val value to be substracted * @returns I128Val or `Error` (errorTypeObject, errorCodeArithDomain) if overflow occurred. */ export function i128Sub(lhs:I128Val, rhs:I128Val) : Val { let a256 = getI256FromI128(lhs); let b256 = getI256FromI128(rhs); let ru256 = i256_sub(a256, b256); return getI128FromI256(ru256); } /** * Performs signed integer subtraction. Computes `lhs - rhs`. * Uses the i256_sub host function to perform the subtraction. * @param lhs I256Val value to substract from * @param rhs I256Val value to be substracted * @returns I256Val (I256Small or I256Object) so that no overflow can occur. */ export function i128SubToI256(lhs:I128Val, rhs:I128Val) : I256Val { let a256 = getI256FromI128(lhs); let b256 = getI256FromI128(rhs); return i256_sub(a256, b256); } /** * Performs checked signed integer multiplication. Computes `lhs * rhs`. * Uses the i256_mul host function to perform the multiplication. * @param lhs I256Val value to be multiplied * @param rhs I256Val value to multiply with * @returns I128Val or `Error` (errorTypeObject, errorCodeArithDomain) if overflow occurred. */ export function i128Mul(lhs:I128Val, rhs:I128Val) : Val { let a256 = getI256FromI128(lhs); let b256 = getI256FromI128(rhs); let ru256 = i256_mul(a256, b256); return getI128FromI256(ru256); } /** * Performs signed integer multiplication. Computes `lhs * rhs`. * Uses the i256_mul host function to perform the multiplication. * @param lhs I256Val value to be multiplied * @param rhs I256Val value to multiply with * @returns I256Val (I256Small or I256Object) so that no overflow can occur. */ export function i128MulToI256(lhs:I128Val, rhs:I128Val) : I256Val { let a256 = getI256FromI128(lhs); let b256 = getI256FromI128(rhs); return i256_mul(a256, b256); } /** * Performs checked signed integer division. Computes `lhs / rhs`. * Uses the i256_div host function to perform the division. * @param lhs I256Val value to be devided * @param rhs I256Val value to devide by * @returns I128Val or `Error` (errorTypeObject, errorCodeArithDomain) if rhs == 0. */ export function i128Div(lhs:I128Val, rhs:I128Val) : Val { let b256 = getI256FromI128OrErrorIfZero(rhs); if (isError(b256)) { return b256; } let a256 = getI256FromI128(lhs); let ri256 = i256_div(a256, b256); return getI128FromI256(ri256); } /** * Multiplies and devides i128 numbers without overflow in multiplication part (number * numerator / denominator). * Traps if not I128Val (I128Object or I128SmallVal) values. * @param number number to multiply with numerator I128Val. * @param numerator numerator to be multiplied with number I128Val. * @param denominator denominator I128Val. * @returns I128Val as the result of number * numerator / denominator or `Error` (errorTypeObject, errorCodeArithDomain) on overflow. */ export function i128MulDiv(number:I128Val, numerator:I128Val, denominator: I128Val) : Val { let number256 = getI256FromI128(number); let numerator256 = getI256FromI128(numerator); let denominator256 = getI256FromI128OrErrorIfZero(denominator); let ru256 = i256_div(i256_mul(number256, numerator256), denominator256); return getI128FromI256(ru256); } /** * Multiplies and devides i128 numbers without overflow in multiplication part (number * numerator / denominator). * Traps if not I128Val (I128Object or I128SmallVal) values. * @param number number to multiply with numerator I128Val. * @param numerator numerator to be multiplied with number I128Val. * @param denominator denominator I128Val. * @returns I256Val as the result of number * numerator / denominator or `Error` (errorTypeObject, errorCodeArithDomain) on overflow. */ export function i128MulDivToI256(number:I128Val, numerator:I128Val, denominator: I128Val) : I256Val { let number256 = getI256FromI128(number); let numerator256 = getI256FromI128(numerator); let denominator256 = getI256FromI128OrErrorIfZero(denominator); return i256_div(i256_mul(number256, numerator256), denominator256); } /** * Performs checked signed integer Euclidean modulo. Computes `lhs % rhs` * Uses the i256_rem_euclid host function to perform the modulo. * @param lhs I256Val base value * @param rhs I256Val mod value * @returns I128Val or `Error` (errorTypeObject, errorCodeArithDomain) if rhs == 0. */ export function i128RemEuclid(lhs:I128Val, rhs:I128Val) : Val { let b256 = getI256FromI128OrErrorIfZero(rhs); if (isError(b256)) { return b256; } let a256 = getI256FromI128(lhs); let ri256 = i256_rem_euclid(a256, b256); return getI128FromI256(ri256); } /** * Performs checked signed integer exponentiation. Computes `lhs.exp(rhs)`. * Uses the i256_pow host function to perform the exponentiation. * @param lhs I256Val base value * @param rhs I256Val exponent value * @returns I128Val or `Error` (errorTypeObject, errorCodeArithDomain) if overflow occurred. */ export function i128Pow(lhs:I128Val, rhs:U32Val) : Val { let a256 = getI256FromI128(lhs); let ri256 = i256_pow(a256, rhs); return getI128FromI256(ri256); } /** * Performs signed integer exponentiation. Computes `lhs.exp(rhs)`. * Uses the i256_pow host function to perform the exponentiation. * @param lhs I256Val base value * @param rhs I256Val exponent value * @returns I256Val (I256Small or I256Object). Traps if i256 overflow occurs. */ export function i128PowToI256(lhs:I128Val, rhs:U32Val) : I256Val { let a256 = getI256FromI128(lhs); return i256_pow(a256, rhs); } /** * Performs checked signed integer shift left. Computes `lhs << rhs`. * Uses the i256_shl host function to perform the shift left. * @param lhs I256Val value to shift left * @param rhs U32Val value to shift left by * @returns I128Val or `Error` (errorTypeObject, errorCodeArithDomain) if overflow occurred. */ export function i128Shl(lhs:I128Val, rhs:U32Val) : Val { let a256 = getI256FromI128(lhs); let ri256 = i256_shl(a256, rhs); return getI128FromI256(ri256); } /** * Performs signed integer shift left. Computes `lhs << rhs`, * Uses the i256_shl host function to perform the shift left. * Traps if i256 overflow occurs. * @param lhs I256Val value to shift left * @param rhs U32Val value to shift left by * @returns I256Val (I256Small or I256Object) */ export function i128ShlToI256(lhs:I128Val, rhs:U32Val) : Val { let a256 = getI256FromI128(lhs); return i256_shl(a256, rhs); } /** * Performs checked signed integer shift right. Computes `lhs >> rhs`. * Uses the i256_shr host function to perform the shift right. * Traps if i256_shr error occurs (if `rhs` is larger than or equal to the number of bits in `lhs`) * @param lhs I256Val value to shift right * @param rhs U32Val value to shift right by * @returns I128Val or `Error` (errorTypeObject, errorCodeArithDomain) if overflow occurred. */ export function i128Shr(lhs:I128Val, rhs:U32Val) : Val { let a256 = getI256FromI128(lhs); let ri256 = i256_shr(a256, rhs); return getI128FromI256(ri256); } /** * Performs signed integer shift right. Computes `lhs >> rhs`. * Uses the i256_shr host function to perform the shift right. * Traps if i256_shr error occurs (if `rhs` is larger than or equal to the number of bits in `lhs`) * @param lhs I256Val value to shift right * @param rhs U32Val value to shift right by * @returns I256Val (I256Small or I256Object) */ export function i128ShrToI256(lhs:U128Val, rhs:U32Val) : Val { let a256 = getI256FromI128(lhs); return i256_shr(a256, rhs); } /***************** UTIL *****************/ /** * Returns true if the given I128Val is negative, otherwise flase. * @param value I128Val value to check if it is < 0 * @returns true if the given value < 0, otherwise false. */ export function isI128Negative(value:I128Val) : bool { if (isI128Small(value)) { return toI128Small(value) < 0; } else if (isI128Object(value)) { return toI128High64(value) < 0; } else { context.fail(); return 0; } } /** * Compares two U128Val. Returns -1 if a<b, 1 if a>b, or 0 if a==b. * Traps if any of the given values is not U128Val. * @param a U128Val first value * @param b U128Val second value * @returns -1 if a<b, 1 if a>b, or 0 if a==b. */ export function u128Compare(a:U128Val, b:U128Val) : i64 { if (isU128Small(a) && isU128Small(b)) { let sa = toU128Small(a); let sb = toU128Small(b); // Returns -1 if a<b, 1 if a>b, or 0 if a==b. if (sa < sb) { return -1; } else if (sa > sb) { return 1; } else { return 0; } } return obj_cmp(a, b); } /** * Checks if a U128Val value (a) is greater then another U128Val (b). * Returns true if a > b. Traps if any of the given values is not U128Val. * @param a U128Val value to check if it is greater then b * @param b U128Val value to check if it is smaller then a * @returns Returns true if a > b, otherwise false. */ export function u128IsGreaterThan(a:U128Val, b:U128Val) : bool { return u128Compare(a,b) == 1; } /** * Checks if a U128Val value (a) is smaller then another U128Val (b). * Returns true if a < b. Traps if any of the given values is not U128Val. * @param a U128Val value to check if it is lower/smaller then b * @param b U128Val value to check if it is greater then a * @returns Returns true if a < b, otherwise false */ export function u128IsLowerThan(a:U128Val, b:U128Val) : bool { return u128Compare(a,b) == -1; } /** * Checks if a U128Val value (a) is equal to another U128Val (b). * Returns true if a == b. Traps if any of the given values is not U128Val. * @param a U128Val value to check if it is equal to b * @param b U128Val value to check if it is equal to a * @returns Returns true if a == b, otherwise false */ export function u128IsEqual(a:U128Val, b:U128Val) : bool { return u128Compare(a,b) == 0; } /** * Compares two I128Val. Returns -1 if a<b, 1 if a>b, or 0 if a==b. * Traps if any of the given values is not I128Val. * @param a I128Val first value * @param b I128Val second value * @returns -1 if a<b, 1 if a>b, or 0 if a==b. */ export function i128Compare(a:I128Val, b:I128Val) : i64 { if (isI128Small(a) && isI128Small(b)) { let sa = toI128Small(a); let sb = toI128Small(b); // Returns -1 if a<b, 1 if a>b, or 0 if a==b. if (sa < sb) { return -1; } else if (sa > sb) { return 1; } else { return 0; } } return obj_cmp(a, b); } /** * Checks if a I128Val value (a) is greater then another I128Val (b). * Returns true if a > b. Traps if any of the given values is not I128Val. * @param a I128Val value to check if it is greater then b * @param b I128Val value to check if it is smaller then a * @returns Returns true if a > b, otherwise false. */ export function i128IsGreaterThan(a:I128Val, b:I128Val) : bool { return i128Compare(a, b) == 1; } /** * Checks if a I128Val value (a) is smaller then another I128Val (b). * Returns true if a < b. Traps if any of the given values is not I128Val. * @param a I128Val value to check if it is lower/smaller then b * @param b I128Val value to check if it is greater then a * @returns Returns true if a < b, otherwise false */ export function i128IsLowerThan(a:I128Val, b:I128Val) : bool { return i128Compare(a, b) == -1; } /** * Checks if a I128Val value (a) is equal to another I128Val (b). * Returns true if a == b. Traps if any of the given values is not I128Val. * @param a I128Val value to check if it is equal to b * @param b I128Val value to check if it is equal to a * @returns Returns true if a == b, otherwise false */ export function i128IsEqual(a:I128Val, b:I128Val) : bool { return i128Compare(a, b) == 0; } /***************** HELPERS *****************/ function getU256FromU128(value:U128Val) : U256Val { if (isU128Small(value)) { return fromU256Small(toU128Small(value)); } else if (isU128Object(value)) { let u128lo = toU128Low64(value); let u128hi = toU128High64(value); return fromU256Pieces(0, 0, u128hi, u128lo); } else { context.fail(); return 0; } } function getU256FromU128OrErrorIfZero(value:U128Val) : U256Val { if (isU128Small(value)) { let small = toU128Small(value); if (small == 0) { return fromError(errorTypeObject, errorCodeArithDomain); } return fromU256Small(small); } else if (isU128Object(value)) { let u128lo = toU128Low64(value); let u128hi = toU128High64(value); if (u128lo == 0 && u128hi == 0) { return fromError(errorTypeObject, errorCodeArithDomain); } return fromU256Pieces(0, 0, u128hi, u128lo); } else { context.fail(); return 0; } } function getI256FromU128(value:U128Val) : I256Val { if (isU128Small(value)) { return fromI256Small(toU128Small(value)); } else if (isU128Object(value)) { let u128lo = toU128Low64(value); let u128hi = toU128High64(value); return fromI256Pieces(0, 0, u128hi, u128lo); } else { context.fail(); return 0; } } function getU128FromU256(value:U256Val) : Val { if(isU256Small(value)) { let rlo = toU256Small(value); return fromU128Small(rlo); } else if (isU256Object(value) && toU256HiLo(value) == 0 && toU256HiHi(value) == 0) { let u256lolo = toU256LoLo(value); let u256lohi = toU256LoHi(value); return fromU128Pieces(u256lohi, u256lolo); } else { return fromError(errorTypeObject, errorCodeArithDomain); } } function getU128FromI256(value:I256Val) : Val { if(isI256Small(value)) { let rlo = toI256Small(value); if (rlo < 0) { return fromError(errorTypeObject, errorCodeArithDomain); } return fromU128Small(rlo); } else if (isI256Object(value) && toI256HiLo(value) == 0 && toI256HiHi(value) == 0) { let i256lolo = toI256LoLo(value); let i256lohi = toI256LoHi(value); return fromU128Pieces(i256lohi, i256lolo); } else { return fromError(errorTypeObject, errorCodeArithDomain); } } function getI256FromI128(value:I128Val) : I256Val { if (isI128Small(value)) { return fromI256Small(toI128Small(value)); } else if (isI128Object(value)) { let i256Bytes = i128ObjectToI256BeBytes(value); return i256_val_from_be_bytes(i256Bytes); } else { context.fail(); return 0; } } function i128ObjectToI256BeBytes(value:I128Object) : BytesObject { let i128hi = toI128High64(value); let i256Bytes = new Bytes(); for (let i = 0; i < 16; ++i) { if (i128hi < 0) { i256Bytes.push(0xFF); } else { i256Bytes.push(0); } } let i128HiBeBytes = bswap<i64>(i128hi); for (let i = 0; i < 8; ++i) { i256Bytes.push(i128HiBeBytes as u8); i128HiBeBytes = (i128HiBeBytes >> 8) } let i128lo = toI128Low64(value); let i128LoBeBytes = bswap<u64>(i128lo); for (let i = 0; i < 8; ++i) { i256Bytes.push(i128LoBeBytes as u8); i128LoBeBytes = (i128LoBeBytes >> 8) } return i256Bytes.getHostObject(); } function getI256FromI128OrErrorIfZero(value:I128Val) : Val { if (isI128Small(value)) { let small = toI128Small(value); if (small == 0) { return fromError(errorTypeObject, errorCodeArithDomain); } return fromI256Small(small); } else if (isI128Object(value)) { let i128lo = toI128Low64(value); let i128hi = toI128High64(value); if (i128lo == 0 && i128hi == 0) { return fromError(errorTypeObject, errorCodeArithDomain); } let i256Bytes = i128ObjectToI256BeBytes(value); return i256_val_from_be_bytes(i256Bytes); } else { context.fail(); return 0; } } function getI128FromI256(value:I256Val) : Val { if(isI256Small(value)) { let rlo = toI256Small(value); return fromI128Small(rlo); } else if (isI256Object(value)) { let i256hihi = toI256HiHi(value); let i128BEBytes = (new Bytes(i256_val_to_be_bytes(value))).slice(16,32); let hi:i64 = 0; for (let i = 0; i < 8; ++i) { hi <<= 8; let val = i128BEBytes.get(i); hi |= val; } let lo:u64 = 0; for (let i = 8; i < 16; ++i) { lo <<= 8; let val = i128BEBytes.get(i); lo |= val; } if ((i256hihi == 0 && hi >= 0) || (i256hihi == -1 && hi < 0)) { return fromI128Pieces(hi, lo); } } return fromError(errorTypeObject, errorCodeArithDomain); }