liba 0.1.15

An algorithm library based on C/C++
Documentation
#include "a.h"
#include "a/regress_simple.h"

static JSClassID liba_regress_simple_class_id;

static void liba_regress_simple_finalizer(JSRuntime *rt, JSValue val)
{
    js_free_rt(rt, JS_GetOpaque(val, liba_regress_simple_class_id));
}

static JSClassDef liba_regress_simple_class = {"regress_simple", .finalizer = liba_regress_simple_finalizer};

static JSValue liba_regress_simple_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)
{
    (void)argc;
    JSValue proto, clazz = JS_UNDEFINED;
    a_regress_simple *const self = (a_regress_simple *)js_mallocz(ctx, sizeof(a_regress_simple));
    if (!self) { return JS_EXCEPTION; }
    double args[] = {1, 0};
    if (argc > (int)A_LEN(args)) { argc = (int)A_LEN(args); }
    for (int i = 0; i < argc; ++i)
    {
        if (JS_ToFloat64(ctx, &args[i], argv[i])) { goto fail; }
    }
    a_regress_simple_init(self, args[0], args[1]);
    proto = JS_GetPropertyStr(ctx, new_target, "prototype");
    if (JS_IsException(proto)) { goto fail; }
    clazz = JS_NewObjectProtoClass(ctx, proto, liba_regress_simple_class_id);
    JS_FreeValue(ctx, proto);
    if (JS_IsException(clazz)) { goto fail; }
    JS_SetOpaque(clazz, self);
    return clazz;
fail:
    js_free(ctx, self);
    JS_FreeValue(ctx, clazz);
    return JS_UNDEFINED;
}

static JSValue liba_regress_simple_eval(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
    (void)argc;
    a_regress_simple *const self = (a_regress_simple *)JS_GetOpaque2(ctx, this_val, liba_regress_simple_class_id);
    if (!self) { return JS_EXCEPTION; }
    double x;
    if (JS_ToFloat64(ctx, &x, argv[0])) { return JS_EXCEPTION; }
    return JS_NewFloat64(ctx, (double)a_regress_simple_eval(self, (a_float)x));
}

static JSValue liba_regress_simple_evar(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
    (void)argc;
    a_regress_simple *const self = (a_regress_simple *)JS_GetOpaque2(ctx, this_val, liba_regress_simple_class_id);
    if (!self) { return JS_EXCEPTION; }
    double x;
    if (JS_ToFloat64(ctx, &x, argv[0])) { return JS_EXCEPTION; }
    return JS_NewFloat64(ctx, (double)a_regress_simple_evar(self, (a_float)x));
}

static JSValue liba_regress_simple_ols_(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
    (void)argc;
    a_regress_simple *const self = (a_regress_simple *)JS_GetOpaque2(ctx, this_val, liba_regress_simple_class_id);
    if (!self) { return JS_EXCEPTION; }
    a_u32 x_n = 0, y_n = 0;
    JSValue err = JS_EXCEPTION;
    a_float *x = NULL, *y = NULL, x_mean, y_mean;
    if (js_array_length(ctx, argv[0], &x_n)) { goto fail; }
    if (js_array_length(ctx, argv[1], &y_n)) { goto fail; }
    x = (a_float *)js_mallocz(ctx, sizeof(a_float) * x_n);
    if (js_array_num_get(ctx, argv[0], x, x_n)) { goto fail_x; }
    y = (a_float *)js_mallocz(ctx, sizeof(a_float) * y_n);
    if (js_array_num_get(ctx, argv[1], y, y_n)) { goto fail_y; }
    if (JS_ToFloat64(ctx, &x_mean, argv[2])) { goto fail_y; }
    if (JS_ToFloat64(ctx, &y_mean, argv[3])) { goto fail_y; }
    a_regress_simple_ols_(self, A_MIN(x_n, y_n), x, y, x_mean, y_mean);
    err = JS_UNDEFINED;
fail_y:
    js_free(ctx, y);
fail_x:
    js_free(ctx, x);
fail:
    return err;
}

static JSValue liba_regress_simple_olsx(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
    (void)argc;
    a_regress_simple *const self = (a_regress_simple *)JS_GetOpaque2(ctx, this_val, liba_regress_simple_class_id);
    if (!self) { return JS_EXCEPTION; }
    a_u32 x_n = 0, y_n = 0;
    JSValue err = JS_EXCEPTION;
    a_float *x = NULL, *y = NULL, x_mean;
    if (js_array_length(ctx, argv[0], &x_n)) { goto fail; }
    if (js_array_length(ctx, argv[1], &y_n)) { goto fail; }
    x = (a_float *)js_mallocz(ctx, sizeof(a_float) * x_n);
    if (js_array_num_get(ctx, argv[0], x, x_n)) { goto fail_x; }
    y = (a_float *)js_mallocz(ctx, sizeof(a_float) * y_n);
    if (js_array_num_get(ctx, argv[1], y, y_n)) { goto fail_y; }
    if (JS_ToFloat64(ctx, &x_mean, argv[2])) { goto fail_y; }
    a_regress_simple_olsx(self, A_MIN(x_n, y_n), x, y, x_mean);
    err = JS_UNDEFINED;
fail_y:
    js_free(ctx, y);
fail_x:
    js_free(ctx, x);
fail:
    return err;
}

static JSValue liba_regress_simple_olsy(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
    (void)argc;
    a_regress_simple *const self = (a_regress_simple *)JS_GetOpaque2(ctx, this_val, liba_regress_simple_class_id);
    if (!self) { return JS_EXCEPTION; }
    a_u32 x_n = 0, y_n = 0;
    JSValue err = JS_EXCEPTION;
    a_float *x = NULL, *y = NULL, y_mean;
    if (js_array_length(ctx, argv[0], &x_n)) { goto fail; }
    if (js_array_length(ctx, argv[1], &y_n)) { goto fail; }
    x = (a_float *)js_mallocz(ctx, sizeof(a_float) * x_n);
    if (js_array_num_get(ctx, argv[0], x, x_n)) { goto fail_x; }
    y = (a_float *)js_mallocz(ctx, sizeof(a_float) * y_n);
    if (js_array_num_get(ctx, argv[1], y, y_n)) { goto fail_y; }
    if (JS_ToFloat64(ctx, &y_mean, argv[2])) { goto fail_y; }
    a_regress_simple_olsy(self, A_MIN(x_n, y_n), x, y, y_mean);
    err = JS_UNDEFINED;
fail_y:
    js_free(ctx, y);
fail_x:
    js_free(ctx, x);
fail:
    return err;
}

static JSValue liba_regress_simple_ols(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
    (void)argc;
    a_regress_simple *const self = (a_regress_simple *)JS_GetOpaque2(ctx, this_val, liba_regress_simple_class_id);
    if (!self) { return JS_EXCEPTION; }
    a_u32 x_n = 0, y_n = 0;
    JSValue err = JS_EXCEPTION;
    a_float *x = NULL, *y = NULL;
    if (js_array_length(ctx, argv[0], &x_n)) { goto fail; }
    if (js_array_length(ctx, argv[1], &y_n)) { goto fail; }
    x = (a_float *)js_mallocz(ctx, sizeof(a_float) * x_n);
    if (js_array_num_get(ctx, argv[0], x, x_n)) { goto fail_x; }
    y = (a_float *)js_mallocz(ctx, sizeof(a_float) * y_n);
    if (js_array_num_get(ctx, argv[1], y, y_n)) { goto fail_y; }
    a_regress_simple_ols(self, A_MIN(x_n, y_n), x, y);
    err = JS_UNDEFINED;
fail_y:
    js_free(ctx, y);
fail_x:
    js_free(ctx, x);
fail:
    return err;
}

static JSValue liba_regress_simple_zero(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
    (void)argc;
    (void)argv;
    a_regress_simple *const self = (a_regress_simple *)JS_GetOpaque2(ctx, this_val, liba_regress_simple_class_id);
    if (!self) { return JS_EXCEPTION; }
    a_regress_simple_zero(self);
    return JS_UNDEFINED;
}

enum
{
    self_coef,
    self_bias,
};

static JSValue liba_regress_simple_get(JSContext *ctx, JSValueConst this_val, int magic)
{
    a_regress_simple *const self = (a_regress_simple *)JS_GetOpaque2(ctx, this_val, liba_regress_simple_class_id);
    if (!self) { return JS_EXCEPTION; }
    double x;
    switch (magic)
    {
    case self_coef: x = (double)self->coef; break;
    case self_bias: x = (double)self->bias; break;
    default: return JS_UNDEFINED;
    }
    return JS_NewFloat64(ctx, x);
}

static JSValue liba_regress_simple_set(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic)
{
    a_regress_simple *const self = (a_regress_simple *)JS_GetOpaque2(ctx, this_val, liba_regress_simple_class_id);
    if (!self) { return JS_EXCEPTION; }
    double x;
    if (JS_ToFloat64(ctx, &x, val)) { return JS_EXCEPTION; }
    switch (magic)
    {
    case self_coef: self->coef = (a_float)x; break;
    case self_bias: self->bias = (a_float)x; break;
    default:
        break;
    }
    return JS_UNDEFINED;
}

static JSCFunctionListEntry const liba_regress_simple_proto[] = {
    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "a.regress_simple", 0),
    JS_CGETSET_MAGIC_DEF("coef", liba_regress_simple_get, liba_regress_simple_set, self_coef),
    JS_CGETSET_MAGIC_DEF("bias", liba_regress_simple_get, liba_regress_simple_set, self_bias),
    JS_CFUNC_DEF("eval", 1, liba_regress_simple_eval),
    JS_CFUNC_DEF("evar", 1, liba_regress_simple_evar),
    JS_CFUNC_DEF("ols_", 4, liba_regress_simple_ols_),
    JS_CFUNC_DEF("olsx", 3, liba_regress_simple_olsx),
    JS_CFUNC_DEF("olsy", 3, liba_regress_simple_olsy),
    JS_CFUNC_DEF("ols", 2, liba_regress_simple_ols),
    JS_CFUNC_DEF("zero", 0, liba_regress_simple_zero),
};

int js_liba_regress_simple_init(JSContext *ctx, JSModuleDef *m)
{
    JS_NewClassID(&liba_regress_simple_class_id);
    JS_NewClass(JS_GetRuntime(ctx), liba_regress_simple_class_id, &liba_regress_simple_class);

    JSValue const proto = JS_NewObject(ctx);
    JS_SetPropertyFunctionList(ctx, proto, liba_regress_simple_proto, A_LEN(liba_regress_simple_proto));

    JSValue const clazz = JS_NewCFunction2(ctx, liba_regress_simple_ctor, "regress_simple", 2, JS_CFUNC_constructor, 0);
    JS_SetConstructor(ctx, clazz, proto);
    JS_SetClassProto(ctx, liba_regress_simple_class_id, proto);

    return JS_SetModuleExport(ctx, m, "regress_simple", clazz);
}