4
* Copyright Ericsson AB 2010. All Rights Reserved.
6
* The contents of this file are subject to the Erlang Public License,
7
* Version 1.1, (the "License"); you may not use this file except in
8
* compliance with the License. You should have received a copy of the
9
* Erlang Public License along with this software. If not, it can be
10
* retrieved online at http://www.erlang.org/.
12
* Software distributed under the License is distributed on an "AS IS"
13
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
* the License for the specific language governing rights and limitations
20
* Purpose: Simple example of NIFs using resource objects to implement functions
21
* for matrix calculations.
36
#define POS(MX, ROW, COL) ((MX)->data[(ROW)* (MX)->ncols + (COL)])
38
static int get_number(ErlNifEnv* env, ERL_NIF_TERM term, double* dp);
39
static Matrix* alloc_matrix(ErlNifEnv* env, unsigned nrows, unsigned ncols);
40
static void matrix_dtor(ErlNifEnv* env, void* obj);
43
static ErlNifResourceType* resource_type = NULL;
45
static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
47
ErlNifResourceType* rt = enif_open_resource_type(env, "matrix_nif_example",
49
ERL_NIF_RT_CREATE, NULL);
53
assert(resource_type == NULL);
58
static ERL_NIF_TERM create(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
60
/* create(Nrows, Ncolumns, [[first row],[second row],...,[last row]]) -> Matrix */
61
unsigned nrows, ncols;
63
ERL_NIF_TERM list, row, ret;
66
if (!enif_get_uint(env, argv[0], &nrows) || nrows < 1 ||
67
!enif_get_uint(env, argv[1], &ncols) || ncols < 1) {
71
mx = alloc_matrix(env, nrows, ncols);
73
for (i = 0; i<nrows; i++) {
74
if (!enif_get_list_cell(env, list, &row, &list)) {
77
for (j = 0; j<ncols; j++) {
79
if (!enif_get_list_cell(env, row, &v, &row) ||
80
!get_number(env, v, &POS(mx,i,j))) {
84
if (!enif_is_empty_list(env, row)) {
88
if (!enif_is_empty_list(env, list)) {
92
ret = enif_make_resource(env, mx);
93
enif_release_resource(env, mx);
98
enif_release_resource(env,mx);
100
return enif_make_badarg(env);
104
static ERL_NIF_TERM pos(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
106
/* pos(Matrix, Row, Column) -> float() */
109
if (!enif_get_resource(env, argv[0], resource_type, (void**)&mx) ||
110
!enif_get_uint(env, argv[1], &i) || (--i >= mx->nrows) ||
111
!enif_get_uint(env, argv[2], &j) || (--j >= mx->ncols)) {
112
return enif_make_badarg(env);
114
return enif_make_double(env, POS(mx, i,j));
117
static ERL_NIF_TERM add(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
119
/* add(Matrix_A, Matrix_B) -> Matrix_Sum */
126
if (!enif_get_resource(env, argv[0], resource_type, (void**)&mxA) ||
127
!enif_get_resource(env, argv[1], resource_type, (void**)&mxB) ||
128
mxA->nrows != mxB->nrows ||
129
mxB->ncols != mxB->ncols) {
131
return enif_make_badarg(env);
133
mxS = alloc_matrix(env, mxA->nrows, mxA->ncols);
134
for (i = 0; i < mxA->nrows; i++) {
135
for (j = 0; j < mxA->ncols; j++) {
136
POS(mxS, i, j) = POS(mxA, i, j) + POS(mxB, i, j);
139
ret = enif_make_resource(env, mxS);
140
enif_release_resource(env, mxS);
144
static ERL_NIF_TERM size_of(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
146
/* size(Matrix) -> {Nrows, Ncols} */
148
if (!enif_get_resource(env, argv[0], resource_type, (void**)&mx)) {
149
return enif_make_badarg(env);
151
return enif_make_tuple2(env, enif_make_uint(env, mx->nrows),
152
enif_make_uint(env, mx->ncols));
155
static ERL_NIF_TERM to_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
157
/* to_term(Matrix) -> [[first row], [second row], ...,[last row]] */
162
if (!enif_get_resource(env, argv[0], resource_type, (void**)&mx)) {
163
return enif_make_badarg(env);
165
res = enif_make_list(env, 0);
166
for (i = mx->nrows; i-- > 0; ) {
167
ERL_NIF_TERM row = enif_make_list(env, 0);
168
for (j = mx->ncols; j-- > 0; ) {
169
row = enif_make_list_cell(env, enif_make_double(env, POS(mx,i,j)),
172
res = enif_make_list_cell(env, row, res);
177
static int get_number(ErlNifEnv* env, ERL_NIF_TERM term, double* dp)
180
return enif_get_double(env, term, dp) ||
181
(enif_get_long(env, term, &i) && (*dp=(double)i, 1));
184
static Matrix* alloc_matrix(ErlNifEnv* env, unsigned nrows, unsigned ncols)
186
Matrix* mx = enif_alloc_resource(env, resource_type, sizeof(Matrix));
189
mx->data = enif_alloc(env, nrows*ncols*sizeof(double));
193
static void matrix_dtor(ErlNifEnv* env, void* obj)
195
Matrix* mx = (Matrix*) obj;
196
enif_free(env, mx->data);
200
static ErlNifFunc nif_funcs[] =
202
{"create", 3, create},
205
{"size_of", 1, size_of},
206
{"to_term", 1, to_term}
209
ERL_NIF_INIT(matrix_nif,nif_funcs,load,NULL,NULL,NULL);