janet/examples/numarray/numarray.c

130 lines
3.4 KiB
C

#include <stdlib.h>
#include <janet.h>
typedef struct {
double *data;
size_t size;
} num_array;
static num_array *num_array_init(num_array *array, size_t size) {
array->data = (double *)janet_calloc(size, sizeof(double));
array->size = size;
return array;
}
static void num_array_deinit(num_array *array) {
janet_free(array->data);
}
static int num_array_gc(void *p, size_t s) {
(void) s;
num_array *array = (num_array *)p;
num_array_deinit(array);
return 0;
}
int num_array_get(void *p, Janet key, Janet *out);
void num_array_put(void *p, Janet key, Janet value);
static const JanetAbstractType num_array_type = {
"numarray",
num_array_gc,
NULL,
num_array_get,
num_array_put,
JANET_ATEND_PUT
};
static Janet num_array_new(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
int32_t size = janet_getinteger(argv, 0);
num_array *array = (num_array *)janet_abstract(&num_array_type, sizeof(num_array));
num_array_init(array, size);
return janet_wrap_abstract(array);
}
static Janet num_array_scale(int32_t argc, Janet *argv) {
janet_fixarity(argc, 2);
num_array *array = (num_array *)janet_getabstract(argv, 0, &num_array_type);
double factor = janet_getnumber(argv, 1);
size_t i;
for (i = 0; i < array->size; i++) {
array->data[i] *= factor;
}
return argv[0];
}
static Janet num_array_sum(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
num_array *array = (num_array *)janet_getabstract(argv, 0, &num_array_type);
double sum = 0;
for (size_t i = 0; i < array->size; i++) sum += array->data[i];
return janet_wrap_number(sum);
}
void num_array_put(void *p, Janet key, Janet value) {
size_t index;
num_array *array = (num_array *)p;
if (!janet_checkint(key))
janet_panic("expected integer key");
if (!janet_checktype(value, JANET_NUMBER))
janet_panic("expected number value");
index = (size_t)janet_unwrap_integer(key);
if (index < array->size) {
array->data[index] = janet_unwrap_number(value);
}
}
static Janet num_array_length(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
num_array *array = (num_array *)janet_getabstract(argv, 0, &num_array_type);
return janet_wrap_number(array->size);
}
static const JanetMethod methods[] = {
{"scale", num_array_scale},
{"sum", num_array_sum},
{"length", num_array_length},
{NULL, NULL}
};
int num_array_get(void *p, Janet key, Janet *out) {
size_t index;
num_array *array = (num_array *)p;
if (janet_checktype(key, JANET_KEYWORD))
return janet_getmethod(janet_unwrap_keyword(key), methods, out);
if (!janet_checkint(key))
janet_panic("expected integer key");
index = (size_t)janet_unwrap_integer(key);
if (index >= array->size) {
return 0;
} else {
*out = janet_wrap_number(array->data[index]);
}
return 1;
}
static const JanetReg cfuns[] = {
{
"new", num_array_new,
"(numarray/new size)\n\n"
"Create new numarray"
},
{
"scale", num_array_scale,
"(numarray/scale numarray factor)\n\n"
"scale numarray by factor"
},
{
"sum", num_array_sum,
"(numarray/sum numarray)\n\n"
"sums numarray"
},
{NULL, NULL, NULL}
};
JANET_MODULE_ENTRY(JanetTable *env) {
janet_cfuns(env, "numarray", cfuns);
}