385 lines
9 KiB
C
385 lines
9 KiB
C
#include <errno.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "utils.h"
|
|
#include "xvec.h"
|
|
|
|
int xvec_init(xvec_t* v, int count, int elsize)
|
|
{
|
|
if ((v == NULL) || (count <= 0) || (elsize <= 0)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
v->data = (void*)calloc(count, elsize);
|
|
if (v->data == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
v->count = count;
|
|
v->elsize = elsize;
|
|
|
|
return v->count;
|
|
}
|
|
|
|
void xvec_fini(xvec_t* v)
|
|
{
|
|
if (v == NULL) {
|
|
return;
|
|
}
|
|
|
|
FREEUP(v->data);
|
|
memset(v, 0x0, sizeof(*v));
|
|
}
|
|
|
|
int xvec_zero(xvec_t* v)
|
|
{
|
|
if (v == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (v->data == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
memset(v->data, 0x0, v->count * v->elsize);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int xvec_resize(xvec_t* v, int new_size)
|
|
{
|
|
void* p = NULL;
|
|
|
|
if (v == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (new_size <= v->count) {
|
|
/* do thing for shrink now */
|
|
return 0;
|
|
}
|
|
|
|
p = (void*)realloc(v->data, new_size * v->elsize);
|
|
if (p == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
v->data = p;
|
|
/* zero fill the extended space */
|
|
memset(((char*)p) + v->count * v->elsize, 0x0,
|
|
(new_size - v->count) * v->elsize);
|
|
v->count = new_size;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define X_OP(op) X_OP_##op
|
|
#define X_OP_add +=
|
|
#define X_OP_sub -=
|
|
|
|
#define DEFINE_VEC_OP(op, typ) \
|
|
static inline int vec_##typ##_##op(typ* v1, typ* v2, int count) \
|
|
{ \
|
|
int i; \
|
|
for (i = 0; i < count; i++) { \
|
|
v1[i] X_OP(op) v2[i]; \
|
|
} \
|
|
return 0; \
|
|
}
|
|
|
|
DEFINE_VEC_OP(add, int)
|
|
DEFINE_VEC_OP(sub, int)
|
|
DEFINE_VEC_OP(add, float)
|
|
DEFINE_VEC_OP(sub, float)
|
|
|
|
int xvec_op(xvec_t* v1, xvec_t* v2, xvec_op_t op)
|
|
{
|
|
int rc = 0;
|
|
|
|
if ((v1 == NULL) || (v2 == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (v1->elsize != v2->elsize) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (op) {
|
|
case XVEC_ADD_INT:
|
|
case XVEC_SUB_INT:
|
|
if (v1->elsize != sizeof(int)) {
|
|
return -EINVAL;
|
|
}
|
|
break;
|
|
case XVEC_ADD_FLOAT:
|
|
case XVEC_SUB_FLOAT:
|
|
if (v1->elsize != sizeof(float)) {
|
|
return -EINVAL;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (v1->count < v2->count) {
|
|
rc = xvec_resize(v1, v2->count);
|
|
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
switch (op) {
|
|
case XVEC_ADD_INT:
|
|
rc = vec_int_add((int*)v1->data, (int*)v2->data, v2->count);
|
|
break;
|
|
case XVEC_SUB_INT:
|
|
rc = vec_int_sub((int*)v1->data, (int*)v2->data, v2->count);
|
|
break;
|
|
case XVEC_ADD_FLOAT:
|
|
rc = vec_float_add((float*)v1->data, (float*)v2->data, v2->count);
|
|
break;
|
|
case XVEC_SUB_FLOAT:
|
|
rc = vec_float_sub((float*)v1->data, (float*)v2->data, v2->count);
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xvec_dup(xvec_t** dst, xvec_t* src)
|
|
{
|
|
xvec_t* v = NULL;
|
|
|
|
v = (xvec_t*)calloc(1, sizeof(*v));
|
|
*dst = v;
|
|
|
|
if (v == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
v->data = (void*)calloc(src->count, src->elsize);
|
|
if (v->data == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
memcpy(v->data, src->data, src->elsize * src->count);
|
|
v->elsize = src->elsize;
|
|
v->count = src->count;
|
|
|
|
return v->count;
|
|
}
|
|
|
|
int xvec_put(xvec_t* v, int idx, void* data)
|
|
{
|
|
int rc;
|
|
char* p;
|
|
|
|
if ((v == NULL) || (idx < 0) || (data == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = xvec_resize(v, idx + 1);
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
p = (char*)v->data;
|
|
memcpy(p + v->elsize * idx, data, v->elsize);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int xvec_get(xvec_t* v, int idx, void* data)
|
|
{
|
|
char* p = NULL;
|
|
|
|
if ((v == NULL) || (idx < 0) || (data == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (idx >= v->count) {
|
|
memset(data, 0x0, v->elsize);
|
|
return 0;
|
|
}
|
|
|
|
p = (char*)v->data;
|
|
memcpy(data, p + v->elsize * idx, v->elsize);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int xvec_idval_init(xvec_idval_t* v, int initsize)
|
|
{
|
|
int rc;
|
|
|
|
if ((v == NULL) || (initsize <= 0)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
memset(v, 0x0, sizeof(*v));
|
|
rc = xvec_init(&(v->idxs), initsize, sizeof(int));
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
rc = xvec_init(&(v->vals), initsize, sizeof(float));
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
v->count = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void xvec_idval_fini(xvec_idval_t* v)
|
|
{
|
|
if (v == NULL) {
|
|
return;
|
|
}
|
|
|
|
xvec_fini(&(v->idxs));
|
|
xvec_fini(&(v->vals));
|
|
|
|
memset(v, 0x0, sizeof(*v));
|
|
return;
|
|
}
|
|
|
|
int xvec_idval_store(xvec_idval_t* v, int idx, float val)
|
|
{
|
|
int rc;
|
|
int pos;
|
|
|
|
if ((v == NULL) || (idx < 0)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
pos = v->count;
|
|
rc = xvec_put(&(v->idxs), pos, &idx);
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
rc = xvec_put(&(v->vals), pos, &val);
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
v->count = pos + 1;
|
|
|
|
return v->count;
|
|
}
|
|
|
|
int xvec_idval_store_idx(xvec_idval_t* v, int idx)
|
|
{
|
|
int pos;
|
|
int rc;
|
|
|
|
if ((v == NULL) || (idx < 0)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
pos = v->count;
|
|
rc = xvec_put(&(v->idxs), pos, &idx);
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
v->count = pos + 1;
|
|
return v->count;
|
|
}
|
|
|
|
int xvec_fill_idval(xvec_idval_t* v, xvec_t* src)
|
|
{
|
|
int i;
|
|
|
|
if ((v == NULL) || (src == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (v->count < 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (src->elsize != sizeof(float)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (i = 0; i < v->count; i++) {
|
|
int idx = ((int*)v->idxs.data)[i];
|
|
float* vals = (float*)v->vals.data;
|
|
|
|
if (idx < 0) {
|
|
vals[i] = 0.0;
|
|
continue;
|
|
}
|
|
|
|
if (idx >= src->count) {
|
|
vals[i] = 0.0;
|
|
} else {
|
|
vals[i] = ((float*)src->data)[idx];
|
|
}
|
|
}
|
|
|
|
return v->count;
|
|
}
|
|
|
|
#define DEFINE_XVEC_IDVAL_OP(op) \
|
|
static inline int xvec_idval_##op(xvec_t* d, xvec_idval_t* v) \
|
|
{ \
|
|
int rc, maxidx; \
|
|
int i; \
|
|
\
|
|
maxidx = 0; \
|
|
for (i = 0; i < v->count; i++) { \
|
|
if (maxidx < ((int*)v->idxs.data)[i]) { \
|
|
maxidx = ((int*)v->idxs.data)[i]; \
|
|
} \
|
|
} \
|
|
\
|
|
rc = xvec_resize(d, maxidx + 1); \
|
|
if (rc < 0) { \
|
|
return rc; \
|
|
} \
|
|
\
|
|
for (i = 0; i < v->count; i++) { \
|
|
int idx = ((int*)v->idxs.data)[i]; \
|
|
\
|
|
if (idx < 0) { \
|
|
continue; \
|
|
} \
|
|
\
|
|
((float*)d->data)[idx] X_OP(op)((float*)v->vals.data)[i]; \
|
|
} \
|
|
\
|
|
return v->count; \
|
|
}
|
|
|
|
DEFINE_XVEC_IDVAL_OP(add)
|
|
DEFINE_XVEC_IDVAL_OP(sub)
|
|
|
|
int xvec_idval(xvec_t* d, xvec_idval_t* v, xvec_op_t op)
|
|
{
|
|
if ((d == NULL) || (v == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (d->elsize != sizeof(float)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ((v->idxs.elsize != sizeof(int)) || (v->vals.elsize != sizeof(float))) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (op) {
|
|
case XVEC_ADD_INT:
|
|
case XVEC_SUB_INT:
|
|
return -EINVAL;
|
|
case XVEC_ADD_FLOAT:
|
|
return xvec_idval_add(d, v);
|
|
case XVEC_SUB_FLOAT:
|
|
return xvec_idval_sub(d, v);
|
|
}
|
|
|
|
return -EINVAL;
|
|
}
|