Skip to content

BigMathUnsafe ​

Git Source

the number is divided into two parts: a coefficient and an exponent. This comes at a cost of losing some precision at the end of the number because the exponent simply fills it with zeroes. This precision is oftentimes negligible and can result in significant gas cost reduction due to storage space reduction. Also note, Valid big number is as follows: if the exponent is > 0, then coefficient last bits should be occupied to have max precision

roundUp is more like a increase 1, which happens everytime for the same number. roundDown simply sets trailing digits after coefficientSize to zero (floor), only once to the same number.

State Variables ​

ROUND_DOWN ​

constants to use for roundUp input param to increase readability

solidity
bool internal constant ROUND_DOWN = false;

ROUND_UP ​

solidity
bool internal constant ROUND_UP = true;

Functions ​

toBigNumber ​

converts normal number to BigNumber with exponent and coefficient (or precision). e.g.: 5035703444687813576399599 (normal) = (coefficient[32bits], exponent[8bits])[40bits] 5035703444687813576399599 (decimal) => 10000101010010110100000011111011110010100110100000000011100101001101001101011101111 (binary) => 10000101010010110100000011111011000000000000000000000000000000000000000000000000000 ^-------------------- 51(exponent) -------------- ^ coefficient = 1000,0101,0100,1011,0100,0000,1111,1011 (2236301563) exponent = 0011,0011 (51) bigNumber = 1000,0101,0100,1011,0100,0000,1111,1011,0011,0011 (572493200179)

solidity
function toBigNumber(uint256 normal, uint256 coefficientSize, uint256 exponentSize, bool roundUp)
    internal
    pure
    returns (uint256 bigNumber);

Parameters

NameTypeDescription
normaluint256number which needs to be converted into Big Number
coefficientSizeuint256at max how many bits of precision there should be (64 = uint64 (64 bits precision))
exponentSizeuint256at max how many bits of exponent there should be (8 = uint8 (8 bits exponent))
roundUpboolsignals if result should be rounded down or up

Returns

NameTypeDescription
bigNumberuint256converted bigNumber (coefficient << exponent)

toBigNumberExtended ​

see BigMathUnsafe-toBigNumber, but returns coefficient and exponent too

solidity
function toBigNumberExtended(uint256 normal, uint256 coefficientSize, uint256 exponentSize, bool roundUp)
    internal
    pure
    returns (uint256 coefficient, uint256 exponent, uint256 bigNumber);

fromBigNumber ​

get normal number from BigNumber coefficient and exponent. e.g.: (coefficient[32bits], exponent[8bits])[40bits] => (normal) (2236301563, 51) = 100001010100101101000000111110110000000000000000000000000000000000000000000000000 coefficient = 1000,0101,0100,1011,0100,0000,1111,1011 (2236301563) exponent = 0011,0011 (51) normal = 10000101010010110100000011111011000000000000000000000000000000000000000000000000000 (5035703442907428892442624) ^-------------------- 51(exponent) -------------- ^

solidity
function fromBigNumber(uint256 coefficient, uint256 exponent) internal pure returns (uint256 normal);

fromBigNumber ​

get normal number from bigNumber, exponentSize and exponentMask

solidity
function fromBigNumber(uint256 bigNumber, uint256 exponentSize, uint256 exponentMask)
    internal
    pure
    returns (uint256 normal);

mulDivNormal ​

multiplies a normal number with a bigNumber1 and then divides by bigNumber2, with exponentSize and exponentMask being used for both bigNumbers. e.g. res = normal * bigNumber1 / bigNumber2 normal: normal number 281474976710656 bigNumber1: bigNumber 265046402172 [(0011,1101,1011,0101,1111,1111,0010,0100)Coefficient, (0111,1100)Exponent] bigNumber2: bigNumber 178478830197 [(0010 1001 1000 1110 0010 1010 1101 0010)Coefficient, (0111 0101)Exponent

solidity
function mulDivNormal(
    uint256 normal,
    uint256 bigNumber1,
    uint256 bigNumber2,
    uint256 exponentSize,
    uint256 exponentMask
) internal pure returns (uint256 res);

Returns

NameTypeDescription
resuint256normal number 53503841411969141

decompileBigNumber ​

decompiles a bigNumber into coefficient and exponent, based on exponentSize and exponentMask. e.g. bigNumber[40bits] => coefficient[32bits], exponent[8bits] 1000,0101,0100,1011,0100,0000,1111,1011,0011,0011 => coefficient = 1000,0101,0100,1011,0100,0000,1111,1011 (2236301563) exponent = 0011,0011 (51)

solidity
function decompileBigNumber(uint256 bigNumber, uint256 exponentSize, uint256 exponentMask)
    internal
    pure
    returns (uint256 coefficient, uint256 exponent);

mostSignificantBit ​

gets the most significant bit lastBit of a normal number (length of given number of binary format). e.g. 5035703444687813576399599 = 10000101010010110100000011111011110010100110100000000011100101001101001101011101111 lastBit = ^--------------------------------- 83 ----------------------------------------^

solidity
function mostSignificantBit(uint256 normal) internal pure returns (uint256 lastBit);

mulDivBigNumber ​

multiplies a bigNumber with normal number1 and then divides by normal number2. exponentSize and exponentMask are used for the input bigNumber and the result is a BigNumber with coefficientSize and exponentSize.

solidity
function mulDivBigNumber(
    uint256 bigNumber,
    uint256 number1,
    uint256 number2,
    uint256 precisionBits,
    uint256 coefficientSize,
    uint256 exponentSize,
    uint256 exponentMask,
    bool roundUp
) internal pure returns (uint256 result);

Parameters

NameTypeDescription
bigNumberuint256Coefficient
number1uint256normal number. Eg:- 32421421413532
number2uint256normal number. Eg:- 91897739843913
precisionBitsuint256precision bits should be set such that, (((Coefficient * number1) << precisionBits) / number2) > max coefficient possible
coefficientSizeuint256coefficient size. Eg: 8 bits, 56 btits, etc
exponentSizeuint256exponent size. Eg: 4 bits, 12 btits, etc
exponentMaskuint256exponent mask. (1 << exponentSize) - 1
roundUpboolis true then roundUp, default it's round down

Returns

NameTypeDescription
resultuint256bigNumber * number1 / number2. Note bigNumber can't get directly multiplied or divide by normal numbers. TODO: Add an example which can help in better understanding. Didn't converted into assembly as overflow checks are good to have

mulBigNumber ​

multiplies a bigNumber1 with another bigNumber2. e.g. res = bigNumber1 * bigNumber2 = [(coe1, exp1) * (coe2, exp2)] >> decimal = (coe1coe2>>overflow, exp1+exp2+overflow-decimal)*

solidity
function mulBigNumber(
    uint256 bigNumber1,
    uint256 bigNumber2,
    uint256 coefficientSize,
    uint256 exponentSize,
    uint256 decimal
) internal pure returns (uint256 res);

Parameters

NameTypeDescription
bigNumber1uint256BigNumber format with coefficient and exponent
bigNumber2uint256BigNumber format with coefficient and exponent
coefficientSizeuint256max size of coefficient, same for both bigNumber1 and bigNumber2
exponentSizeuint256max size of exponent, same for both bigNumber1 and bigNumber2
decimaluint256decimals in bits

Returns

NameTypeDescription
resuint256BigNumber format with coefficient and exponent

divBigNumber ​

divides a bigNumber1 by bigNumber2. e.g. res = bigNumber1 / bigNumber2 = [(coe1, exp1) / (coe2, exp2)] << decimal = ((coe1<<precision_)/coe2, exp1+decimal-exp2-precision_)

solidity
function divBigNumber(
    uint256 bigNumber1,
    uint256 bigNumber2,
    uint256 coefficientSize,
    uint256 exponentSize,
    uint256 precision_,
    uint256 decimal
) internal pure returns (uint256 res);

Parameters

NameTypeDescription
bigNumber1uint256BigNumber format with coefficient and exponent
bigNumber2uint256BigNumber format with coefficient and exponent
coefficientSizeuint256max size of coefficient, same for both bigNumber1 and bigNumber2
exponentSizeuint256max size of exponent, same for both bigNumber1 and bigNumber2
precision_uint256precision bit
decimaluint256decimals in bits

Returns

NameTypeDescription
resuint256BigNumber format with coefficient and exponent