Current section

Files

Jump to
mmath c_src bin_nif.c
Raw

c_src/bin_nif.c

#include "erl_nif.h"
#include "mmath.h"
#include <math.h>
static int
load(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info)
{
return 0;
}
static int
upgrade(ErlNifEnv* env, void** priv, void** old_priv, ERL_NIF_TERM load_info)
{
return 0;
}
static ERL_NIF_TERM
to_list(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary a;
ERL_NIF_TERM *acc;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64 last = 0;
unsigned count;
if (argc != 1)
return enif_make_badarg(env);
GET_BIN(0, a, count, vs);
acc = malloc(count * sizeof(ERL_NIF_TERM));
for (unsigned i = 0 ; i < count; i++) {
if (IS_SET(vs[i]))
last = FROM_DDB(vs[i]);
acc[i] = enif_make_int64(env, last);
}
r = enif_make_list_from_array(env, acc, count);
free(acc);
return r;
}
static ERL_NIF_TERM
from_list(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM list;
ERL_NIF_TERM cell;
ErlNifSInt64 v;
ErlNifSInt64* target;
ERL_NIF_TERM r;
unsigned count;
if (argc != 1)
return enif_make_badarg(env);
list = argv[0];
if (!enif_get_list_length(env, list, &count))
return enif_make_badarg(env);
if (!(target = (ErlNifSInt64*) enif_make_new_binary(env, count * sizeof(ErlNifSInt64), &r)))
return enif_make_badarg(env); // TODO return propper error
for (int i = 0; i < count; i++) {
if (! enif_get_list_cell(env, list, &cell, &list))
return enif_make_badarg(env); // TODO return propper error
if (!enif_get_int64(env, cell, &v))
return enif_make_badarg(env);
target[i] = TO_DDB(v);
}
return r;
}
static ERL_NIF_TERM
realize(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary a;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64* target;
ErlNifSInt64 last = 0;
int count;
if (argc != 1)
return enif_make_badarg(env);
GET_BIN(0, a, count, vs);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, count * sizeof(ErlNifSInt64), &r)))
return enif_make_badarg(env); // TODO return propper error
for (int i = 0; i < count; i++) {
if (IS_SET(vs[i])) {
last = FROM_DDB(vs[i]);
};
target[i] = last;
}
return r;
}
derealize(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary a;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64* target;
int count;
if (argc != 1)
return enif_make_badarg(env);
GET_BIN(0, a, count, vs);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, count * sizeof(ErlNifSInt64), &r)))
return enif_make_badarg(env); // TODO return propper error
for (int i = 0; i < count; i++) {
target[i] = TO_DDB(vs[i]);
}
return r;
}
static ErlNifFunc nif_funcs[] = {
{"from_list", 1, from_list},
{"to_list", 1, to_list},
{"realize", 1, realize},
{"derealize", 1, derealize}
};
// Initialize this NIF library.
//
// Args: (MODULE, ErlNifFunc funcs[], load, reload, upgrade, unload)
// Docs: http://erlang.org/doc/man/erl_nif.html#ERL_NIF_INIT
ERL_NIF_INIT(mmath_bin, nif_funcs, &load, NULL, &upgrade, NULL);