aboutsummaryrefslogtreecommitdiff
path: root/nerv/lib/matrix/generic/matrix.c
blob: e4afa37204609aa2f7d9f5c86aafdffccfe87a2c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#ifdef NERV_GENERIC_MATRIX
#include "../../common.h"
#include "matrix.h"
/* FIXME: malloc failure detection */

static void nerv_matrix_(data_free)(Matrix *self, Status *status) {
    assert(*self->data_ref > 0);
    if (--(*self->data_ref) == 0)
    {
        /* free matrix data */
        MATRIX_DATA_FREE(MATRIX_ELEM_PTR(self), status);
        free(self->data_ref);
        free(self);
    }
    else {
        free(self);
        NERV_SET_STATUS(status, NERV_NORMAL, 0);
    }
}

static void nerv_matrix_(data_retain)(Matrix *self) {
    (*self->data_ref)++;
}

Matrix *nerv_matrix_(create)(long nrow, long ncol, Status *status) {
    Matrix *self = (Matrix *)malloc(sizeof(Matrix));
    self->nrow = nrow;
    self->ncol = ncol;
    self->nmax = self->nrow * self->ncol;
    self->dim = 2;
    MATRIX_DATA_ALLOC(&MATRIX_ELEM_PTR(self), &self->stride,
                     sizeof(MATRIX_ELEM) * self->ncol, self->nrow,
                     status);
    if (status->err_code != NERV_NORMAL)
    {
        free(self);
        return NULL;
    }
    self->data_ref = (long *)malloc(sizeof(long));
    *self->data_ref = 0;
    nerv_matrix_(data_retain)(self);
    NERV_SET_STATUS(status, NERV_NORMAL, 0);
    return self;
}

void nerv_matrix_(destroy)(Matrix *self, Status *status) {
    nerv_matrix_(data_free)(self, status);
}

Matrix *nerv_matrix_(getrow)(Matrix *self, int row) {
    Matrix *prow = (Matrix *)malloc(sizeof(Matrix));
    prow->ncol = self->ncol;
    prow->nrow = 1;
    prow->dim = 1;
    prow->stride = self->stride;
    prow->nmax = prow->ncol;
    MATRIX_ELEM_PTR(prow) = MATRIX_ROW_PTR(self, row);
    prow->data_ref = self->data_ref;
    nerv_matrix_(data_retain)(prow);
    return prow;
}
#endif