This commit is contained in:
Spooks
2024-03-06 11:03:26 -07:00
parent 913127854c
commit c43d9d3bdd
4 changed files with 367 additions and 1 deletions

View File

@@ -78,3 +78,13 @@ App(
requires=["js_app"],
sources=["modules/js_blebeacon.c"],
)
App(
appid="js_math",
apptype=FlipperAppType.PLUGIN,
entry_point="js_math_ep",
requires=["js_app"],
sources=["modules/js_math.c"],
)

View File

@@ -0,0 +1,47 @@
let math = require("math");
let absResult = math.abs(-5);
let acosResult = math.acos(0.5);
let acoshResult = math.acosh(2);
let asinResult = math.asin(0.5);
let asinhResult = math.asinh(2);
let atanResult = math.atan(1);
let atan2Result = math.atan2(1, 1);
let atanhResult = math.atanh(0.5);
let cbrtResult = math.cbrt(27);
let ceilResult = math.ceil(5.3);
let clz32Result = math.clz32(1);
let cosResult = math.cos(math.PI);
let expResult = math.exp(1);
let floorResult = math.floor(5.7);
let maxResult = math.max(3, 5);
let minResult = math.min(3, 5);
let powResult = math.pow(2, 3);
let randomResult = math.random();
let signResult = math.sign(-5);
let sinResult = math.sin(math.PI / 2);
let sqrtResult = math.sqrt(25);
let truncResult = math.trunc(5.7);
print("math.abs(-5):", absResult);
print("math.acos(0.5):", acosResult);
print("math.acosh(2):", acoshResult);
print("math.asin(0.5):", asinResult);
print("math.asinh(2):", asinhResult);
print("math.atan(1):", atanResult);
print("math.atan2(1, 1):", atan2Result);
print("math.atanh(0.5):", atanhResult);
print("math.cbrt(27):", cbrtResult);
print("math.ceil(5.3):", ceilResult);
print("math.clz32(1):", clz32Result);
print("math.cos(math.PI):", cosResult);
print("math.exp(1):", expResult);
print("math.floor(5.7):", floorResult);
print("math.max(3, 5):", maxResult);
print("math.min(3, 5):", minResult);
print("math.pow(2, 3):", powResult);
print("math.random():", randomResult);
print("math.sign(-5):", signResult);
print("math.sin(math.PI/2):", sinResult);
print("math.sqrt(25):", sqrtResult);
print("math.trunc(5.7):", truncResult);

View File

@@ -9,7 +9,7 @@ typedef struct {
GapExtraBeaconConfig beacon_config;
} JSblebeaconInst;
// Define the OUI Map as a constant array of structs
struct OUI_MAP_ENTRY {
const char *brand;
const char *oui;

View File

@@ -0,0 +1,309 @@
#include "../js_modules.h"
#include "furi_hal_random.h"
#define MJS_PI (double)3.14159265358979323846
#define MJS_E (double)2.7182818284590452354
static void ret_bad_args(struct mjs* mjs, const char* error) {
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "%s", error);
mjs_return(mjs, mjs_mk_undefined());
}
static bool check_arg_count(struct mjs* mjs, size_t count) {
size_t num_args = mjs_nargs(mjs);
if(num_args != count) {
ret_bad_args(mjs, "Wrong argument count");
return false;
}
return true;
}
void mjs_abs(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
mjs_return(mjs, x < 0 ? mjs_mk_number(mjs, -x) : mjs_arg(mjs, 0));
}
void mjs_acos(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
if (x < -1 || x > 1) {
ret_bad_args(mjs, "Invalid input value for Math.acos");
mjs_return(mjs, MJS_UNDEFINED);
}
mjs_return(mjs, mjs_mk_number(mjs, MJS_PI / (double)2 - atan(x / sqrt(1 - x * x))));
}
void mjs_acosh(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
if (x < 1) {
ret_bad_args(mjs, "Invalid input value for Math.acosh");
mjs_return(mjs, MJS_UNDEFINED);
}
mjs_return(mjs, mjs_mk_number(mjs, log(x + sqrt(x * x - 1))));
}
void mjs_asin(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
mjs_return(mjs, mjs_mk_number(mjs, atan(x / sqrt(1 - x * x))));
}
void mjs_asinh(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
mjs_return(mjs, mjs_mk_number(mjs, log(x + sqrt(x * x + 1))));
}
void mjs_atan(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
mjs_return(mjs, mjs_mk_number(mjs, atan(x)));
}
void mjs_atan2(struct mjs* mjs) {
if (!check_arg_count(mjs, 2) || !mjs_is_number(mjs_arg(mjs, 0)) || !mjs_is_number(mjs_arg(mjs, 1))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double y = mjs_get_double(mjs, mjs_arg(mjs, 0));
double x = mjs_get_double(mjs, mjs_arg(mjs, 1));
mjs_return(mjs, mjs_mk_number(mjs, atan2(y, x)));
}
void mjs_atanh(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
if (x <= -1 || x >= 1) {
ret_bad_args(mjs, "Invalid input value for Math.atanh");
mjs_return(mjs, MJS_UNDEFINED);
}
mjs_return(mjs, mjs_mk_number(mjs, (double)0.5 * log((1 + x) / (1 - x))));
}
void mjs_cbrt(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
mjs_return(mjs, mjs_mk_number(mjs, pow(x, 1.0 / 3.0)));
}
void mjs_ceil(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
mjs_return(mjs, mjs_mk_number(mjs, (int)(x + (double)0.5)));
}
void mjs_clz32(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
unsigned int x = (unsigned int)mjs_get_int(mjs, mjs_arg(mjs, 0));
int count = 0;
while (x) {
x >>= 1;
count++;
}
mjs_return(mjs, mjs_mk_number(mjs, 32 - count));
}
void mjs_cos(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
mjs_return(mjs, mjs_mk_number(mjs, cos(x)));
}
void mjs_exp(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
double result = 1;
double term = 1;
for (int i = 1; i < 100; i++) {
term *= x / i;
result += term;
}
mjs_return(mjs, mjs_mk_number(mjs, result));
}
void mjs_floor(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
mjs_return(mjs, mjs_mk_number(mjs, (int)x));
}
void mjs_log(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
if (x <= 0) {
ret_bad_args(mjs, "Invalid input value for Math.log");
mjs_return(mjs, MJS_UNDEFINED);
}
double result = 0;
while (x >= MJS_E) {
x /= MJS_E;
result++;
}
mjs_return(mjs, mjs_mk_number(mjs, result + log(x)));
}
void mjs_max(struct mjs* mjs) {
if (!check_arg_count(mjs, 2) || !mjs_is_number(mjs_arg(mjs, 0)) || !mjs_is_number(mjs_arg(mjs, 1))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
double y = mjs_get_double(mjs, mjs_arg(mjs, 1));
mjs_return(mjs, mjs_mk_number(mjs, x > y ? x : y));
}
void mjs_min(struct mjs* mjs) {
if (!check_arg_count(mjs, 2) || !mjs_is_number(mjs_arg(mjs, 0)) || !mjs_is_number(mjs_arg(mjs, 1))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
double y = mjs_get_double(mjs, mjs_arg(mjs, 1));
mjs_return(mjs, mjs_mk_number(mjs, x < y ? x : y));
}
void mjs_pow(struct mjs* mjs) {
if (!check_arg_count(mjs, 2) || !mjs_is_number(mjs_arg(mjs, 0)) || !mjs_is_number(mjs_arg(mjs, 1))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double base = mjs_get_double(mjs, mjs_arg(mjs, 0));
double exponent = mjs_get_double(mjs, mjs_arg(mjs, 1));
double result = 1;
for (int i = 0; i < exponent; i++) {
result *= base;
}
mjs_return(mjs, mjs_mk_number(mjs, result));
}
void mjs_random(struct mjs* mjs) {
if (!check_arg_count(mjs, 0)) {
mjs_return(mjs, MJS_UNDEFINED);
}
const uint32_t random_val = furi_hal_random_get();
double rnd = (double)random_val / RAND_MAX;
mjs_return(mjs, mjs_mk_number(mjs, rnd));
}
void mjs_sign(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
mjs_return(mjs, mjs_mk_number(mjs, x == 0 ? 0 : (x < 0 ? -1 : 1)));
}
void mjs_sin(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
double result = x;
double term = x;
for (int i = 1; i < 10; i++) {
term *= -x * x / ((2 * i) * (2 * i + 1));
result += term;
}
mjs_return(mjs, mjs_mk_number(mjs, result));
}
void mjs_sqrt(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
if (x < 0) {
ret_bad_args(mjs, "Invalid input value for Math.sqrt");
mjs_return(mjs, MJS_UNDEFINED);
}
double result = 1;
while (result * result < x) {
result += (double)0.001;
}
mjs_return(mjs, mjs_mk_number(mjs, result));
}
void mjs_trunc(struct mjs* mjs) {
if (!check_arg_count(mjs, 1) || !mjs_is_number(mjs_arg(mjs, 0))) {
mjs_return(mjs, MJS_UNDEFINED);
}
double x = mjs_get_double(mjs, mjs_arg(mjs, 0));
mjs_return(mjs, mjs_mk_number(mjs, x < 0 ? ceil(x) : floor(x)));
}
static void* js_math_create(struct mjs *mjs, mjs_val_t* object) {
mjs_val_t math_obj = mjs_mk_object(mjs);
mjs_set(mjs, math_obj, "abs", ~0, MJS_MK_FN(mjs_abs));
mjs_set(mjs, math_obj, "acos", ~0, MJS_MK_FN(mjs_acos));
mjs_set(mjs, math_obj, "acosh", ~0, MJS_MK_FN(mjs_acosh));
mjs_set(mjs, math_obj, "asin", ~0, MJS_MK_FN(mjs_asin));
mjs_set(mjs, math_obj, "asinh", ~0, MJS_MK_FN(mjs_asinh));
mjs_set(mjs, math_obj, "atan", ~0, MJS_MK_FN(mjs_atan));
mjs_set(mjs, math_obj, "atan2", ~0, MJS_MK_FN(mjs_atan2));
mjs_set(mjs, math_obj, "atanh", ~0, MJS_MK_FN(mjs_atanh));
mjs_set(mjs, math_obj, "cbrt", ~0, MJS_MK_FN(mjs_cbrt));
mjs_set(mjs, math_obj, "ceil", ~0, MJS_MK_FN(mjs_ceil));
mjs_set(mjs, math_obj, "clz32", ~0, MJS_MK_FN(mjs_clz32));
mjs_set(mjs, math_obj, "cos", ~0, MJS_MK_FN(mjs_cos));
mjs_set(mjs, math_obj, "exp", ~0, MJS_MK_FN(mjs_exp));
mjs_set(mjs, math_obj, "floor", ~0, MJS_MK_FN(mjs_floor));
mjs_set(mjs, math_obj, "log", ~0, MJS_MK_FN(mjs_log));
mjs_set(mjs, math_obj, "max", ~0, MJS_MK_FN(mjs_max));
mjs_set(mjs, math_obj, "min", ~0, MJS_MK_FN(mjs_min));
mjs_set(mjs, math_obj, "pow", ~0, MJS_MK_FN(mjs_pow));
mjs_set(mjs, math_obj, "random", ~0, MJS_MK_FN(mjs_random));
mjs_set(mjs, math_obj, "sign", ~0, MJS_MK_FN(mjs_sign));
mjs_set(mjs, math_obj, "sin", ~0, MJS_MK_FN(mjs_sin));
mjs_set(mjs, math_obj, "sqrt", ~0, MJS_MK_FN(mjs_sqrt));
mjs_set(mjs, math_obj, "trunc", ~0, MJS_MK_FN(mjs_trunc));
mjs_set(mjs, math_obj, "PI", ~0, mjs_mk_number(mjs, MJS_PI));
*object = math_obj;
return object;
}
static void js_math_destroy(void *ptr) {
UNUSED(ptr);
}
static const JsModuleDescriptor js_math_desc = {
"math",
js_math_create,
js_math_destroy,
};
static const FlipperAppPluginDescriptor btkicker_plugin_descriptor = {
.appid = PLUGIN_APP_ID,
.ep_api_version = PLUGIN_API_VERSION,
.entry_point = &js_math_desc,
};
const FlipperAppPluginDescriptor* js_math_ep(void) {
return &btkicker_plugin_descriptor;
}