Packages
mmath
0.1.13
0.2.26
0.2.25
0.2.24
0.2.23
0.2.22
0.2.21
0.2.20
0.2.19
0.2.18
0.2.17
0.2.16
0.2.15
0.2.14
0.2.13
0.2.12
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.2.0-alpha9
0.2.0-alpha8
0.2.0-alpha7
0.2.0-alpha6
0.2.0-alpha5
0.2.0-alpha4
0.2.0-alpha3
0.2.0-alpha2
0.2.0-alpha10
0.2.0-alpha1
0.2.0-alpha
0.1.17-alpha
0.1.16
0.1.15
0.1.14
0.1.13
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
math library for metric sequences and binary arrays.
Current section
Files
Jump to
Current section
Files
c_src/aggr_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
mul(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64 m;
ErlNifSInt64* target;
int count;
if (argc != 2)
return enif_make_badarg(env);
GET_BIN(0, bin, count, vs);
if (!enif_get_int64(env, argv[1], &m))
return enif_make_badarg(env);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, bin.size, &r)))
return enif_make_badarg(env); // TODO return propper error
for (int i = 0; i < count; i++) {
if (IS_SET(vs[i])) {
target[i] = TO_DDB(FROM_DDB(vs[i]) * m);
} else {
target[i] = 0;
}
}
return r;
}
static ERL_NIF_TERM
mul_r(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64 m;
ErlNifSInt64* target;
int count;
if (argc != 2)
return enif_make_badarg(env);
GET_BIN(0, bin, count, vs);
if (!enif_get_int64(env, argv[1], &m))
return enif_make_badarg(env);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, bin.size, &r)))
return enif_make_badarg(env); // TODO return propper error
for (int i = 0; i < count; i++) {
target[i] = vs[i] * m;
}
return r;
}
static ERL_NIF_TERM
divide(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64 m;
ErlNifSInt64* target;
int count;
if (argc != 2)
return enif_make_badarg(env);
GET_BIN(0, bin, count, vs);
if (!enif_get_int64(env, argv[1], &m))
return enif_make_badarg(env);
if (!m)
return enif_make_badarg(env);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, bin.size, &r)))
return enif_make_badarg(env); // TODO return propper error
for (int i = 0; i < count; i++) {
if (IS_SET(vs[i])) {
target[i] = TO_DDB(FROM_DDB(vs[i]) / m);
} else {
target[i] = 0;
}
}
return r;
}
static ERL_NIF_TERM
divide_r(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64 m;
ErlNifSInt64* target;
int count;
if (argc != 2)
return enif_make_badarg(env);
GET_BIN(0, bin, count, vs);
if (!enif_get_int64(env, argv[1], &m))
return enif_make_badarg(env);
if (!m)
return enif_make_badarg(env);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, bin.size, &r)))
return enif_make_badarg(env); // TODO return propper error
for (int i = 0; i < count; i++) {
target[i] = vs[i] / m;
}
return r;
}
static ERL_NIF_TERM
derivate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64 last;
ErlNifSInt64* target;
ErlNifSInt64* vs;
int count;
int has_value;
if (argc != 1)
return enif_make_badarg(env);
GET_BIN(0, bin, count, vs);
if (count < 1) // can't be empty
return enif_make_badarg(env);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, bin.size - sizeof(ErlNifSInt64), &r)))
return enif_make_badarg(env); // TODO return propper error
has_value = IS_SET(vs[0]);
if (has_value) {
last = FROM_DDB(vs[0]);
}
for (int i = 1; i < count; i++) {
if (IS_SET(vs[i])) {
if (has_value) {
ErlNifSInt64 this = FROM_DDB(vs[i]);
target[i - 1] = TO_DDB(this - last);
last = this;
} else {
target[i - 1] = 0;
last = FROM_DDB(vs[i]);
has_value = 1;
}
} else {
if (has_value) {
target[i - 1] = TO_DDB(0);
} else {
target[i - 1] = 0;
}
}
}
return r;
}
static ERL_NIF_TERM
derivate_r(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* target;
ErlNifSInt64* vs;
int count;
if (argc != 1)
return enif_make_badarg(env);
GET_BIN(0, bin, count, vs);
if (count < 1) // can't be empty
return enif_make_badarg(env);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, bin.size - sizeof(ErlNifSInt64), &r)))
return enif_make_badarg(env); // TODO return propper error
for (int i = 1; i < count; i++) {
target[i - 1] = vs[i] - vs[i-1];
}
return r;
}
static ERL_NIF_TERM
empty(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64* target;
ErlNifSInt64 chunk; // size to be compressed
ErlNifSInt64 target_i = 0; // target position
ErlNifSInt64 pos = 0; // position in chunk
ErlNifSInt64 aggr = 0; // aggregated value for this chunk
int count;
int target_size;
if (argc != 2)
return enif_make_badarg(env);
GET_CHUNK(chunk);
GET_BIN(0, bin, count, vs);
count = bin.size / sizeof(ErlNifSInt64);
vs = (ErlNifSInt64 *) bin.data;
target_size = ceil((double) count / chunk) * sizeof(ErlNifSInt64);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, target_size, &r)))
return enif_make_badarg(env); // TODO return propper error
if (count == 0)
return r;
pos = 0;
for (int i = 0; i < count; i++, pos++) {
if (pos == chunk) {
target[target_i] = TO_DDB(aggr);
target_i++;
aggr = !IS_SET(vs[i]);
pos = 0;
} else {
aggr += !IS_SET(vs[i]);
}
}
if (count % chunk) {
aggr += (chunk - (count % chunk));
}
target[target_i] = TO_DDB(aggr);
return r;
}
static ERL_NIF_TERM
min(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64* target;
ErlNifSInt64 chunk; // size to be compressed
ErlNifSInt64 target_i = 0; // target position
ErlNifSInt64 pos = 0; // position in chunk
ErlNifSInt64 aggr = 0; // aggregated value for this chunk
int count;
int has_value = 0;
int target_size;
if (argc != 2)
return enif_make_badarg(env);
GET_CHUNK(chunk);
GET_BIN(0, bin, count, vs);
target_size = ceil((double) count / chunk) * sizeof(ErlNifSInt64);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, target_size, &r)))
return enif_make_badarg(env); // TODO return propper error
// If we don't have any input data we can return right away.
if (count == 0)
return r;
// We know we have at least one element in the list so our
// aggregator will start with this
if (IS_SET(vs[0])) {
aggr = FROM_DDB(vs[0]);
has_value = 1;
};
pos = 1;
// We itterate over the remining i .. count-1 elements
for (int i = 1; i < count; i++, pos++) {
if (pos == chunk) {
if (has_value) {
target[target_i] = TO_DDB(aggr);
} else {
target[target_i] = 0;
}
target_i++;
has_value = IS_SET(vs[i]);
if (has_value) {
aggr = FROM_DDB(vs[i]);
};
pos = 0;
} else if (!has_value) {
if (IS_SET(vs[i])) {
aggr = FROM_DDB(vs[i]);
has_value = 1;
};
} else {
if (IS_SET(vs[i])) {
ErlNifSInt64 v = FROM_DDB(vs[i]);
if (v < aggr) {
aggr = v;
}
}
}
}
if (has_value) {
target[target_i] = TO_DDB(aggr);
} else {
target[target_i] = 0;
}
return r;
}
static ERL_NIF_TERM
min_r(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64* target;
ErlNifSInt64 chunk; // size to be compressed
ErlNifSInt64 target_i = 0; // target position
ErlNifSInt64 aggr; // target position
uint32_t pos;
uint32_t count;
uint32_t target_size;
if (argc != 2)
return enif_make_badarg(env);
GET_CHUNK(chunk);
GET_BIN(0, bin, count, vs);
target_size = ceil((double) count / chunk) * sizeof(ErlNifSInt64);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, target_size, &r)))
return enif_make_badarg(env); // TODO return propper error
// If we don't have any input data we can return right away.
if (count == 0)
return r;
// We know we have at least one element in the list so our
// aggregator will start with this
aggr = vs[0];
pos = 1;
// We itterate over the remining i .. count-1 elements
for (uint32_t i = 1; i < count; i++, pos++) {
if (pos == chunk) {
target[target_i] = aggr;
target_i++;
aggr = vs[i];
pos = 0;
} else {
if (vs[i] < aggr) {
aggr = vs[i];
};
}
}
// Making sure the last aggregate is saved.
if (target_i < target_size)
target[target_i] = aggr;
return r;
}
static ERL_NIF_TERM
max(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64* target;
ErlNifSInt64 chunk; // size to be compressed
ErlNifSInt64 target_i = 0; // target position
ErlNifSInt64 pos = 0; // position in chunk
ErlNifSInt64 aggr = 0; // aggregated value for this chunk
int count;
int has_value = 0;
int target_size;
if (argc != 2)
return enif_make_badarg(env);
GET_CHUNK(chunk);
GET_BIN(0, bin, count, vs);
target_size = ceil((double) count / chunk) * sizeof(ErlNifSInt64);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, target_size, &r)))
return enif_make_badarg(env); // TODO return propper error
// If we don't have any input data we can return right away.
if (count == 0)
return r;
// We know we have at least one element in the list so our
// aggregator will start with this
if (IS_SET(vs[0])) {
aggr = FROM_DDB(vs[0]);
has_value = 1;
};
pos = 1;
// We itterate over the remining i .. count-1 elements
for (int i = 1; i < count; i++, pos++) {
if (pos == chunk) {
if (has_value) {
target[target_i] = TO_DDB(aggr);
} else {
target[target_i] = 0;
}
target_i++;
has_value = IS_SET(vs[i]);
if (has_value) {
aggr = FROM_DDB(vs[i]);
};
pos = 0;
} else if (!has_value) {
if (IS_SET(vs[i])) {
aggr = FROM_DDB(vs[i]);
has_value = 1;
};
} else {
if (IS_SET(vs[i])) {
ErlNifSInt64 v = FROM_DDB(vs[i]);
if (v > aggr) {
aggr = v;
}
}
}
}
if (has_value) {
target[target_i] = TO_DDB(aggr);
} else {
target[target_i] = 0;
}
return r;
}
static ERL_NIF_TERM
max_r(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64* target;
ErlNifSInt64 chunk; // size to be compressed
ErlNifSInt64 target_i = 0; // target position
ErlNifSInt64 aggr; // target position
uint32_t pos;
uint32_t count;
uint32_t target_size;
if (argc != 2)
return enif_make_badarg(env);
GET_CHUNK(chunk);
GET_BIN(0, bin, count, vs);
target_size = ceil((double) count / chunk) * sizeof(ErlNifSInt64);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, target_size, &r)))
return enif_make_badarg(env); // TODO return propper error
// If we don't have any input data we can return right away.
if (count == 0)
return r;
// We know we have at least one element in the list so our
// aggregator will start with this
aggr = vs[0];
pos = 1;
// We itterate over the remining i .. count-1 elements
for (uint32_t i = 1; i < count; i++, pos++) {
if (pos == chunk) {
target[target_i] = aggr;
target_i++;
aggr = vs[i];
pos = 0;
} else {
if (vs[i] > aggr) {
aggr = vs[i];
};
}
}
// Making sure the last aggregate is saved.
target[target_i] = aggr;
return r;
}
static ERL_NIF_TERM
sum(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64* target;
ErlNifSInt64 chunk; // size to be compressed
ErlNifSInt64 target_i = 0; // target position
ErlNifSInt64 pos = 0; // position in chunk
ErlNifSInt64 aggr = 0; // aggregated value for this chunk
ErlNifSInt64 last = 0;
int count;
int has_value = 0;
int has_last = 0;
int target_size;
if (argc != 2)
return enif_make_badarg(env);
GET_CHUNK(chunk);
GET_BIN(0, bin, count, vs);
target_size = ceil((double) count / chunk) * sizeof(ErlNifSInt64);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, target_size, &r)))
return enif_make_badarg(env); // TODO return propper error
// If we don't have any input data we can return right away.
if (count == 0)
return r;
// We know we have at least one element in the list so our
// aggregator will start with this
if (IS_SET(vs[0])) {
aggr = FROM_DDB(vs[0]);
last = aggr;
has_value = 1;
has_last = 1;
};
pos = 1;
// We itterate over the remining i .. count-1 elements
for (int i = 1; i < count; i++, pos++) {
if (pos == chunk) {
if (has_value) {
target[target_i] = TO_DDB(aggr);
} else {
target[target_i] = 0;
}
target_i++;
has_value = IS_SET(vs[i]);
if (has_value) {
aggr = FROM_DDB(vs[i]);
last = aggr;
has_last = 1;
} else if (has_last) {
aggr = last;
has_value = 1;
}
pos = 0;
} else if (!has_value) {
if (IS_SET(vs[i])) {
aggr = FROM_DDB(vs[i]);
last = aggr;
has_value = 1;
has_last = 1;
};
} else {
if (IS_SET(vs[i])) {
last = FROM_DDB(vs[i]);
aggr += last;
has_last = 1;
has_value = 1;
} else if (has_last) {
aggr += last;
has_value = 1;
}
}
}
if (has_value) {
if (count % chunk) {
aggr += (last * (chunk - (count % chunk)));
}
target[target_i] = TO_DDB(aggr);
} else {
target[target_i] = 0;
}
return r;
}
static ERL_NIF_TERM
sum_r(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ErlNifSInt64 chunk; // size to be compressed
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64* target;
ErlNifSInt64 aggr; // Aggregator
uint32_t target_i = 0; // target position
uint32_t count;
uint32_t pos = 0;
uint32_t target_size;
if (argc != 2)
return enif_make_badarg(env);
GET_CHUNK(chunk);
GET_BIN(0, bin, count, vs);
target_size = ceil((double) count / chunk) * sizeof(ErlNifSInt64);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, target_size, &r)))
return enif_make_badarg(env); // TODO return propper error
if (count > 0) {
aggr = vs[0];
pos = 2;
for (uint32_t i = 1; i < count; i++, pos++) {
if (pos == count) {
target[target_i] = aggr;
target_i++;
aggr = vs[i];
pos = 0;
} else {
aggr += vs[i];
}
}
if (count % chunk) {
target[target_i] = aggr + vs[count - 1] * (chunk - (count % chunk));
} else {
target[target_i] = aggr;
}
}
return r;
}
static ERL_NIF_TERM
avg(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64* target;
ErlNifSInt64 chunk; // size to be compressed
ErlNifSInt64 target_i = 0; // target position
ErlNifSInt64 pos = 0; // position in chunk
ErlNifSInt64 aggr = 0; // aggregated value for this chunk
ErlNifSInt64 last = 0;
int count;
int has_value = 0;
int has_last = 0;
int target_size;
if (argc != 2)
return enif_make_badarg(env);
GET_CHUNK(chunk);
GET_BIN(0, bin, count, vs);
target_size = ceil((double) count / chunk) * sizeof(ErlNifSInt64);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, target_size, &r)))
return enif_make_badarg(env); // TODO return propper error
// If we don't have any input data we can return right away.
if (count == 0)
return r;
// We know we have at least one element in the list so our
// aggregator will start with this
if (IS_SET(vs[0])) {
aggr = FROM_DDB(vs[0]);
last = aggr;
has_value = 1;
has_last = 1;
};
pos = 1;
// We itterate over the remining i .. count-1 elements
for (int i = 1; i < count; i++, pos++) {
if (pos == chunk) {
if (has_value) {
target[target_i] = TO_DDB(aggr / chunk);
} else {
target[target_i] = 0;
}
target_i++;
has_value = IS_SET(vs[i]);
if (has_value) {
aggr = FROM_DDB(vs[i]);
last = aggr;
has_last = 1;
} else if (has_last) {
aggr = last;
has_value = 1;
}
pos = 0;
} else if (!has_value) {
if (IS_SET(vs[i])) {
aggr = FROM_DDB(vs[i]);
last = aggr;
has_value = 1;
has_last = 1;
};
} else {
if (IS_SET(vs[i])) {
last = FROM_DDB(vs[i]);
aggr += last;
has_last = 1;
has_value = 1;
} else if (has_last) {
aggr += last;
has_value = 1;
}
}
}
if (has_value) {
if (count % chunk) {
aggr += (last * (chunk - (count % chunk)));
}
target[target_i] = TO_DDB(aggr / chunk);
} else {
target[target_i] = 0;
}
return r;
}
static ERL_NIF_TERM
avg_r(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
ERL_NIF_TERM r;
ErlNifSInt64* vs;
ErlNifSInt64* target;
ErlNifSInt64 chunk; // size to be compressed
ErlNifSInt64 aggr; // Aggregator
uint32_t target_i = 0; // target position
uint32_t count;
uint32_t pos = 0;
uint32_t target_size;
if (argc != 2)
return enif_make_badarg(env);
GET_CHUNK(chunk);
GET_BIN(0, bin, count, vs);
target_size = ceil((double) count / chunk) * sizeof(ErlNifSInt64);
if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, target_size, &r)))
return enif_make_badarg(env); // TODO return propper error
if (count == 0)
return r;
aggr = vs[0];
pos++;
for (uint32_t i = 1; i < count; i++, pos++) {
if (pos == chunk) {
target[target_i] = aggr / chunk;
target_i++;
aggr = vs[i];
pos = 0;
} else {
aggr += vs[i];
}
}
if (count % chunk) {
aggr += vs[count - 1] * (chunk - (count % chunk));
}
target[target_i] = aggr / chunk;
return r;
}
static ErlNifFunc nif_funcs[] = {
{"mul", 2, mul},
{"mul_r", 2, mul_r},
{"divide", 2, divide},
{"divide_r", 2, divide_r},
{"empty", 2, empty},
{"min", 2, min},
{"min_r", 2, min_r},
{"max", 2, max},
{"max_r", 2, max_r},
{"sum", 2, sum},
{"sum_r", 2, sum_r},
{"avg", 2, avg},
{"avg_r", 2, avg_r},
{"derivate", 1, derivate},
{"derivate_r", 1, derivate_r}
};
// 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_aggr, nif_funcs, &load, NULL, &upgrade, NULL);