BigMathUnsafe
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
bool internal constant ROUND_DOWN = false;
ROUND_UP
bool internal constant ROUND_UP = true;
Functions
toBigNumber
converts normal
number to BigNumber with exponent
and coefficient
(or precision).
e.g.:
5035703444687813576399599 (normal) = (coefficient32bits, exponent8bits)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)
function toBigNumber(uint256 normal, uint256 coefficientSize, uint256 exponentSize, bool roundUp)
internal
pure
returns (uint256 bigNumber);
Parameters
Name | Type | Description |
---|---|---|
normal | uint256 | number which needs to be converted into Big Number |
coefficientSize | uint256 | at max how many bits of precision there should be (64 = uint64 (64 bits precision)) |
exponentSize | uint256 | at max how many bits of exponent there should be (8 = uint8 (8 bits exponent)) |
roundUp | bool | signals if result should be rounded down or up |
Returns
Name | Type | Description |
---|---|---|
bigNumber | uint256 | converted bigNumber (coefficient << exponent) |
toBigNumberExtended
see BigMathUnsafe-toBigNumber, but returns coefficient and exponent too
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.:
(coefficient32bits, exponent8bits)40bits => (normal)
(2236301563, 51) = 100001010100101101000000111110110000000000000000000000000000000000000000000000000
coefficient = 1000,0101,0100,1011,0100,0000,1111,1011 (2236301563)
exponent = 0011,0011 (51)
normal = 10000101010010110100000011111011000000000000000000000000000000000000000000000000000 (5035703442907428892442624)
^-------------------- 51(exponent) -------------- ^
function fromBigNumber(uint256 coefficient, uint256 exponent) internal pure returns (uint256 normal);
fromBigNumber
get normal
number from bigNumber
, exponentSize
and exponentMask
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
function mulDivNormal(
uint256 normal,
uint256 bigNumber1,
uint256 bigNumber2,
uint256 exponentSize,
uint256 exponentMask
) internal pure returns (uint256 res);
Returns
Name | Type | Description |
---|---|---|
res | uint256 | normal number 53503841411969141 |
decompileBigNumber
decompiles a bigNumber
into coefficient
and exponent
, based on exponentSize
and exponentMask
.
e.g.
bigNumber40bits => coefficient32bits, exponent8bits
1000,0101,0100,1011,0100,0000,1111,1011,0011,0011 =>
coefficient = 1000,0101,0100,1011,0100,0000,1111,1011 (2236301563)
exponent = 0011,0011 (51)
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 ----------------------------------------^
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
.
function mulDivBigNumber(
uint256 bigNumber,
uint256 number1,
uint256 number2,
uint256 precisionBits,
uint256 coefficientSize,
uint256 exponentSize,
uint256 exponentMask,
bool roundUp
) internal pure returns (uint256 result);
Parameters
Name | Type | Description |
---|---|---|
bigNumber | uint256 | Coefficient |
number1 | uint256 | normal number. Eg:- 32421421413532 |
number2 | uint256 | normal number. Eg:- 91897739843913 |
precisionBits | uint256 | precision bits should be set such that, (((Coefficient * number1) << precisionBits) / number2) > max coefficient possible |
coefficientSize | uint256 | coefficient size. Eg: 8 bits, 56 btits, etc |
exponentSize | uint256 | exponent size. Eg: 4 bits, 12 btits, etc |
exponentMask | uint256 | exponent mask. (1 << exponentSize) - 1 |
roundUp | bool | is true then roundUp, default it's round down |
Returns
Name | Type | Description |
---|---|---|
result | uint256 | bigNumber * 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)*
function mulBigNumber(
uint256 bigNumber1,
uint256 bigNumber2,
uint256 coefficientSize,
uint256 exponentSize,
uint256 decimal
) internal pure returns (uint256 res);
Parameters
Name | Type | Description |
---|---|---|
bigNumber1 | uint256 | BigNumber format with coefficient and exponent |
bigNumber2 | uint256 | BigNumber format with coefficient and exponent |
coefficientSize | uint256 | max size of coefficient, same for both bigNumber1 and bigNumber2 |
exponentSize | uint256 | max size of exponent, same for both bigNumber1 and bigNumber2 |
decimal | uint256 | decimals in bits |
Returns
Name | Type | Description |
---|---|---|
res | uint256 | BigNumber 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_)
function divBigNumber(
uint256 bigNumber1,
uint256 bigNumber2,
uint256 coefficientSize,
uint256 exponentSize,
uint256 precision_,
uint256 decimal
) internal pure returns (uint256 res);
Parameters
Name | Type | Description |
---|---|---|
bigNumber1 | uint256 | BigNumber format with coefficient and exponent |
bigNumber2 | uint256 | BigNumber format with coefficient and exponent |
coefficientSize | uint256 | max size of coefficient, same for both bigNumber1 and bigNumber2 |
exponentSize | uint256 | max size of exponent, same for both bigNumber1 and bigNumber2 |
precision_ | uint256 | precision bit |
decimal | uint256 | decimals in bits |
Returns
Name | Type | Description |
---|---|---|
res | uint256 | BigNumber format with coefficient and exponent |