I'm experimenting with NIFs and I'm confused about what number types Erlang is working with, because I'm getting some weirdness with my precisions.
Here's an example:
erlang:band(18446744073709551614, 5) == 4
And from inside a NIF which looks something like this:
long long l, r;
enif_get_long(env, argv[0], &l);
enif_get_long(env, argv[1], &r);
return enif_make_long(env, l & r);
I get a 1
as a result.
Is this something to do with the C layer not holding the correct "size" of the number? Or is it that enif_(get|make)_long
isn't the correct way to be dealing with a number of this size? Or is it simply that NIFs can't work with numbers this large?
18446744073709551614
is 2^64 - 2
and therefore cannot fit in a long long
, which is most likely a 64 bit signed integer with the range -(2^63)
to (2^63)-1
. Also, enif_get_long
requires a long int
, not long long
. You should also be getting an error value returned from enif_get_long
because of the overflow according to the docs which you are not checking for.
To work on numbers upto 2^64 - 1
(which includes the number in question), you can use enif_get_uint64
.
This code should work (untested):
ErlNifUInt64 l, r;
enif_get_uint64(env, argv[0], &l);
enif_get_uint64(env, argv[1], &r);
return enif_make_uint64(env, l & r);
You should also check the return value of enif_get_*
to make sure you're not working on uninitialized data.