Is there an integer size limit?

The limit for big integers used to be limited by RAM. There has always existed a limit, but in practice one would run out of RAM before reaching the limit for bigints. That is no longer the case, especially when running on a 64-bit computer.

The current limit is about 4 MBits or 4,194,240 bits. The value of BIG_ARITY_MAX should be multiplied by the number of bits in a machine word (32 or 64) to obtain the maximum number of bits.

The limit used to be higher, but we lowered it in Optimize binary_to_integer/1 and friends by bjorng · Pull Request #7426 · erlang/otp · GitHub to ensure that operations on big integers would always finish in a reasonable time.

Just for fun, I did a micro-optimization of your power/2 function:

power(Base, Exp) when is_number(Base), is_integer(Exp),
                      0 =< Exp, Exp =< 1 bsl 24 ->
    {ok, do_power(Base, Exp)};
power(_Base, _Exp) ->
    {error, nil}.

Guard tests can help the JIT to emit better native code. For example, when the exponent is known to be a small integer, the div and rem operations can be simplified. Without the guard tests, the div operation would look like so:

# i_int_div_jIssd
    mov x2, 47
    and x13, x26, 15
    cmp x13, 15
    b.ne L70
# optimized div by replacing with right shift
    orr x0, x13, x26, 1
    b L71
L70:
    mov x1, x26
    mov x3, 4347964816
    bl L73
L71:
    mov x27, x0

The first operand might not be a small integer, so the JIT needs to emit code to handle that. With the guards tests, the code for the div operation can be simplified to:

# i_int_div_jIssd
# skipped test for smalls operands and overflow
    mov x13, 15
# optimized div by replacing with right shift
    orr x26, x13, x26, 1

The runtime of power/2 is dominated by the multiplication of big integers, so the actual reduction in runtime with the guard tests is minuscule.

12 Likes