|
|
|
|
@@ -53,6 +53,69 @@ typedef struct rtree rtree;
|
|
|
|
|
//#include <cblas.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define STATE_VECTOR_LENGTH 624
|
|
|
|
|
#define STATE_VECTOR_M 397 /* changes to STATE_VECTOR_LENGTH also require changes to this */
|
|
|
|
|
|
|
|
|
|
typedef struct tagMTRand {
|
|
|
|
|
uint32_t mt[STATE_VECTOR_LENGTH];
|
|
|
|
|
int32_t index;
|
|
|
|
|
} MTRand;
|
|
|
|
|
|
|
|
|
|
static MTRand mrand;
|
|
|
|
|
|
|
|
|
|
#define UPPER_MASK 0x80000000
|
|
|
|
|
#define LOWER_MASK 0x7fffffff
|
|
|
|
|
#define TEMPERING_MASK_B 0x9d2c5680
|
|
|
|
|
#define TEMPERING_MASK_C 0xefc60000
|
|
|
|
|
|
|
|
|
|
inline static void m_seedRand(MTRand* rand, uint32_t seed) {
|
|
|
|
|
/* set initial seeds to mt[STATE_VECTOR_LENGTH] using the generator
|
|
|
|
|
* from Line 25 of Table 1 in: Donald Knuth, "The Art of Computer
|
|
|
|
|
* Programming," Vol. 2 (2nd Ed.) pp.102.
|
|
|
|
|
*/
|
|
|
|
|
rand->mt[0] = seed & 0xffffffff;
|
|
|
|
|
for(rand->index=1; rand->index<STATE_VECTOR_LENGTH; rand->index++) {
|
|
|
|
|
rand->mt[rand->index] = (6069 * rand->mt[rand->index-1]) & 0xffffffff;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t genRandLong(MTRand* rand) {
|
|
|
|
|
|
|
|
|
|
uint32_t y;
|
|
|
|
|
static uint32_t mag[2] = {0x0, 0x9908b0df}; /* mag[x] = x * 0x9908b0df for x = 0,1 */
|
|
|
|
|
if(rand->index >= STATE_VECTOR_LENGTH || rand->index < 0) {
|
|
|
|
|
/* generate STATE_VECTOR_LENGTH words at a time */
|
|
|
|
|
int32_t kk;
|
|
|
|
|
if(rand->index >= STATE_VECTOR_LENGTH+1 || rand->index < 0) {
|
|
|
|
|
m_seedRand(rand, 4357);
|
|
|
|
|
}
|
|
|
|
|
for(kk=0; kk<STATE_VECTOR_LENGTH-STATE_VECTOR_M; kk++) {
|
|
|
|
|
y = (rand->mt[kk] & UPPER_MASK) | (rand->mt[kk+1] & LOWER_MASK);
|
|
|
|
|
rand->mt[kk] = rand->mt[kk+STATE_VECTOR_M] ^ (y >> 1) ^ mag[y & 0x1];
|
|
|
|
|
}
|
|
|
|
|
for(; kk<STATE_VECTOR_LENGTH-1; kk++) {
|
|
|
|
|
y = (rand->mt[kk] & UPPER_MASK) | (rand->mt[kk+1] & LOWER_MASK);
|
|
|
|
|
rand->mt[kk] = rand->mt[kk+(STATE_VECTOR_M-STATE_VECTOR_LENGTH)] ^ (y >> 1) ^ mag[y & 0x1];
|
|
|
|
|
}
|
|
|
|
|
y = (rand->mt[STATE_VECTOR_LENGTH-1] & UPPER_MASK) | (rand->mt[0] & LOWER_MASK);
|
|
|
|
|
rand->mt[STATE_VECTOR_LENGTH-1] = rand->mt[STATE_VECTOR_M-1] ^ (y >> 1) ^ mag[y & 0x1];
|
|
|
|
|
rand->index = 0;
|
|
|
|
|
}
|
|
|
|
|
y = rand->mt[rand->index++];
|
|
|
|
|
y ^= (y >> 11);
|
|
|
|
|
y ^= (y << 7) & TEMPERING_MASK_B;
|
|
|
|
|
y ^= (y << 15) & TEMPERING_MASK_C;
|
|
|
|
|
y ^= (y >> 18);
|
|
|
|
|
return y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double genRand(MTRand* rand) {
|
|
|
|
|
return((double)genRandLong(rand) / (uint32_t)0xffffffff);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static JSAtom width_atom;
|
|
|
|
|
static JSAtom height_atom;
|
|
|
|
|
static JSAtom l_atom;
|
|
|
|
|
@@ -1754,40 +1817,182 @@ shader_globals camera_globals(JSContext *js, JSValue camera)
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static JSValue floats2array(JSContext *js, float *vals, size_t len) {
|
|
|
|
|
JSValue arr = JS_NewArray(js);
|
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
|
|
JS_SetPropertyUint32(js, arr, i, number2js(js, vals[i]));
|
|
|
|
|
}
|
|
|
|
|
return arr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JSValue js_vector_dot(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
|
|
|
|
JSValue js_math_dot(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
|
|
|
|
size_t alen, blen;
|
|
|
|
|
float *a = js2floats(js,argv[0], &alen);
|
|
|
|
|
float *b = js2floats(js,argv[1], &blen);
|
|
|
|
|
// JSValue ret = number2js(js, cblas_sdot(alen, a, 1, b,1));
|
|
|
|
|
float dot = 0;
|
|
|
|
|
size_t len = alen < blen? alen : blen;
|
|
|
|
|
for (size_t i = 0; i < len; i++)
|
|
|
|
|
dot += a[i] * b[i];
|
|
|
|
|
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
return number2js(js,dot);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_project, ret = vec22js(js,HMM_ProjV2(js2vec2(js,argv[0]), js2vec2(js,argv[1]))))
|
|
|
|
|
JSValue js_math_project(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
|
|
|
|
size_t alen, blen;
|
|
|
|
|
float *a = js2floats(js, argv[0], &alen);
|
|
|
|
|
float *b = js2floats(js, argv[1], &blen);
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_midpoint,
|
|
|
|
|
HMM_Vec2 a = js2vec2(js,argv[0]);
|
|
|
|
|
HMM_Vec2 b = js2vec2(js,argv[1]);
|
|
|
|
|
// HMM_Vec2 c = HMM_AddV2(a,b);
|
|
|
|
|
// c = HMM_Div2VF(c, 2);
|
|
|
|
|
return vec22js(js,(HMM_Vec2){(a.x+b.x)/2, (a.y+b.y)/2});
|
|
|
|
|
)
|
|
|
|
|
if (!a || !b) {
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_distance,
|
|
|
|
|
HMM_Vec2 a = js2vec2(js,argv[0]);
|
|
|
|
|
HMM_Vec2 b = js2vec2(js,argv[1]);
|
|
|
|
|
ret = number2js(js,HMM_DistV2(a,b));
|
|
|
|
|
)
|
|
|
|
|
// We'll work up to the smaller length
|
|
|
|
|
size_t len = (alen < blen) ? alen : blen;
|
|
|
|
|
if (len == 0) {
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_angle,
|
|
|
|
|
HMM_Vec2 a = js2vec2(js,argv[0]);
|
|
|
|
|
ret= angle2js(js,atan2(a.y,a.x));
|
|
|
|
|
)
|
|
|
|
|
// Compute dot products: a·b and b·b
|
|
|
|
|
float ab = 0, bb = 0;
|
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
|
|
ab += a[i] * b[i];
|
|
|
|
|
bb += b[i] * b[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Build the result array
|
|
|
|
|
float *proj = (float*)malloc(sizeof(float) * len);
|
|
|
|
|
if (!proj) {
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return JS_EXCEPTION; // or some error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float scale = (bb != 0.0f) ? (ab / bb) : 0.0f;
|
|
|
|
|
for (size_t i = 0; i < len; i++)
|
|
|
|
|
proj[i] = scale * b[i];
|
|
|
|
|
|
|
|
|
|
JSValue ret = floats2array(js, proj, len);
|
|
|
|
|
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
free(proj);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------
|
|
|
|
|
// math_midpoint(a, b)
|
|
|
|
|
// midpoint = (a + b) / 2
|
|
|
|
|
// returns new vector (array)
|
|
|
|
|
// dimension = min(alen, blen)
|
|
|
|
|
// ---------------------------
|
|
|
|
|
JSValue js_math_midpoint(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
|
|
|
|
size_t alen, blen;
|
|
|
|
|
float *a = js2floats(js, argv[0], &alen);
|
|
|
|
|
float *b = js2floats(js, argv[1], &blen);
|
|
|
|
|
|
|
|
|
|
if (!a || !b) {
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t len = (alen < blen) ? alen : blen;
|
|
|
|
|
if (len == 0) {
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float *m = (float*)malloc(sizeof(float) * len);
|
|
|
|
|
if (!m) {
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return JS_EXCEPTION;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < len; i++)
|
|
|
|
|
m[i] = (a[i] + b[i]) * 0.5f;
|
|
|
|
|
|
|
|
|
|
JSValue ret = floats2array(js, m, len);
|
|
|
|
|
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
free(m);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------
|
|
|
|
|
// math_distance(a, b)
|
|
|
|
|
// Euclidean distance = sqrt( Σ (b[i]-a[i])^2 )
|
|
|
|
|
// dimension = min(alen, blen)
|
|
|
|
|
// returns scalar (number)
|
|
|
|
|
// ---------------------------
|
|
|
|
|
JSValue js_math_distance(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
|
|
|
|
size_t alen, blen;
|
|
|
|
|
float *a = js2floats(js, argv[0], &alen);
|
|
|
|
|
float *b = js2floats(js, argv[1], &blen);
|
|
|
|
|
|
|
|
|
|
if (!a || !b) {
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t len = (alen < blen) ? alen : blen;
|
|
|
|
|
if (len == 0) {
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float distSq = 0.0f;
|
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
|
|
float diff = b[i] - a[i];
|
|
|
|
|
distSq += diff * diff;
|
|
|
|
|
}
|
|
|
|
|
float dist = sqrtf(distSq);
|
|
|
|
|
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return number2js(js, dist);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------
|
|
|
|
|
// math_angle(a)
|
|
|
|
|
// In 2D: angle from x-axis via atan2(y, x).
|
|
|
|
|
// For higher dimensions, there's no single "angle" in the usual sense.
|
|
|
|
|
// We'll only return angle if len >= 2, using first two coords.
|
|
|
|
|
// Or strictly require len==2, your call.
|
|
|
|
|
// ---------------------------
|
|
|
|
|
JSValue js_math_angle(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
|
|
|
|
size_t alen;
|
|
|
|
|
float *a = js2floats(js, argv[0], &alen);
|
|
|
|
|
|
|
|
|
|
if (!a || alen < 2) {
|
|
|
|
|
free(a);
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If you want to be strict, require alen == 2
|
|
|
|
|
// if (alen != 2) {
|
|
|
|
|
// free(a);
|
|
|
|
|
// return JS_UNDEFINED;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
float angle = atan2f(a[1], a[0]);
|
|
|
|
|
free(a);
|
|
|
|
|
return number2js(js, angle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Given a series of points p, computes a new series with them expanded on either side by d */
|
|
|
|
|
/*
|
|
|
|
|
HMM_Vec2 *inflatepoints(HMM_Vec2 *p, float d, int n)
|
|
|
|
|
{
|
|
|
|
|
if (d == 0) {
|
|
|
|
|
@@ -1830,7 +2035,7 @@ HMM_Vec2 *inflatepoints(HMM_Vec2 *p, float d, int n)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_inflate,
|
|
|
|
|
JSC_CCALL(math_inflate,
|
|
|
|
|
HMM_Vec2 *p = js2cpvec2arr(js,argv[0]);
|
|
|
|
|
double d = js2number(js,argv[1]);
|
|
|
|
|
HMM_Vec2 *infl = inflatepoints(p,d, js_arrlen(js,argv[0]));
|
|
|
|
|
@@ -1838,8 +2043,8 @@ JSC_CCALL(vector_inflate,
|
|
|
|
|
arrfree(infl);
|
|
|
|
|
arrfree(p);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_rotate,
|
|
|
|
|
*/
|
|
|
|
|
JSC_CCALL(math_rotate,
|
|
|
|
|
HMM_Vec2 vec = js2vec2(js,argv[0]);
|
|
|
|
|
double angle = js2angle(js, argv[1]);
|
|
|
|
|
HMM_Vec2 pivot = JS_IsUndefined(argv[2]) ? v2zero : js2vec2(js,argv[2]);
|
|
|
|
|
@@ -1865,28 +2070,8 @@ JSC_CCALL(vector_rotate,
|
|
|
|
|
// Convert back to JS and return
|
|
|
|
|
return vec22js(js, vec);
|
|
|
|
|
)
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_rotate,
|
|
|
|
|
HMM_Vec2 vec = js2vec2(js,argv[0]);
|
|
|
|
|
double angle = js2angle(js,argv[1]);
|
|
|
|
|
HMM_Vec2 pivot = JS_IsUndefined(argv[2]) ? v2zero : js2vec2(js,argv[2]);
|
|
|
|
|
vec = HMM_SubV2(vec,pivot);
|
|
|
|
|
float r = HMM_LenV2(vec);
|
|
|
|
|
angle += atan2(vec.y,vec.x);
|
|
|
|
|
vec.x = r*cos(angle);
|
|
|
|
|
vec.y = r*sin(angle);
|
|
|
|
|
return vec22js(js,HMM_AddV2(vec,pivot));
|
|
|
|
|
)
|
|
|
|
|
*/
|
|
|
|
|
JSC_CCALL(vector_add,
|
|
|
|
|
HMM_Vec4 a = js2vec4(js,argv[0]);
|
|
|
|
|
HMM_Vec4 b = js2vec4(js,argv[1]);
|
|
|
|
|
HMM_Vec4 c = HMM_AddV4(a,b);
|
|
|
|
|
ret = vec42js(js,c);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_norm,
|
|
|
|
|
JSC_CCALL(math_norm,
|
|
|
|
|
int len = js_arrlen(js,argv[0]);
|
|
|
|
|
|
|
|
|
|
switch(len) {
|
|
|
|
|
@@ -1904,17 +2089,17 @@ JSC_CCALL(vector_norm,
|
|
|
|
|
ret = newarr;
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_angle_between,
|
|
|
|
|
JSC_CCALL(math_angle_between,
|
|
|
|
|
int len = js_arrlen(js,argv[0]);
|
|
|
|
|
switch(len) {
|
|
|
|
|
case 2: return angle2js(js,HMM_AngleV2(js2vec2(js,argv[0]), js2vec2(js,argv[1])));
|
|
|
|
|
case 3: return angle2js(js,HMM_AngleV3(js2vec3(js,argv[0]), js2vec3(js,argv[1])));
|
|
|
|
|
case 4: return angle2js(js,HMM_AngleV4(js2vec4(js,argv[0]), js2vec4(js,argv[1])));
|
|
|
|
|
}
|
|
|
|
|
ret = angle2js(js,0);
|
|
|
|
|
return JS_ThrowReferenceError(js, "Input array must have a length between 2 and 4.");
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_lerp,
|
|
|
|
|
JSC_CCALL(math_lerp,
|
|
|
|
|
double s = js2number(js,argv[0]);
|
|
|
|
|
double f = js2number(js,argv[1]);
|
|
|
|
|
double t = js2number(js,argv[2]);
|
|
|
|
|
@@ -1928,24 +2113,22 @@ int gcd(int a, int b) {
|
|
|
|
|
return gcd(b, a % b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_gcd,
|
|
|
|
|
ret = number2js(js,gcd(js2number(js,argv[0]), js2number(js,argv[1])));
|
|
|
|
|
)
|
|
|
|
|
JSC_CCALL(math_gcd, ret = number2js(js,gcd(js2number(js,argv[0]), js2number(js,argv[1]))); )
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_lcm,
|
|
|
|
|
JSC_CCALL(math_lcm,
|
|
|
|
|
double a = js2number(js,argv[0]);
|
|
|
|
|
double b = js2number(js,argv[1]);
|
|
|
|
|
ret = number2js(js,(a*b)/gcd(a,b));
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_clamp,
|
|
|
|
|
JSC_CCALL(math_clamp,
|
|
|
|
|
double x = js2number(js,argv[0]);
|
|
|
|
|
double l = js2number(js,argv[1]);
|
|
|
|
|
double h = js2number(js,argv[2]);
|
|
|
|
|
return number2js(js,x > h ? h : x < l ? l : x);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_angledist,
|
|
|
|
|
JSC_CCALL(math_angledist,
|
|
|
|
|
double a1 = js2number(js,argv[0]);
|
|
|
|
|
double a2 = js2number(js,argv[1]);
|
|
|
|
|
a1 = fmod(a1,1);
|
|
|
|
|
@@ -1962,29 +2145,21 @@ JSC_CCALL(vector_angledist,
|
|
|
|
|
return number2js(js,dist);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_length,
|
|
|
|
|
return number2js(js,arr_vec_length(js,argv[0]));
|
|
|
|
|
)
|
|
|
|
|
JSC_CCALL(math_length, return number2js(js,arr_vec_length(js,argv[0])); )
|
|
|
|
|
|
|
|
|
|
double r2()
|
|
|
|
|
double rand_range(double min, double max)
|
|
|
|
|
{
|
|
|
|
|
return (double)rand() / (double)RAND_MAX ;
|
|
|
|
|
return genRand(&mrand) * (max-min)+min;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double rand_range(double min, double max) {
|
|
|
|
|
return r2() * (max-min) + min;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_variate,
|
|
|
|
|
JSC_CCALL(math_jitter,
|
|
|
|
|
double n = js2number(js,argv[0]);
|
|
|
|
|
double pct = js2number(js,argv[1]);
|
|
|
|
|
|
|
|
|
|
return number2js(js,n + (rand_range(-pct,pct)*n));
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_random_range, return number2js(js,rand_range(js2number(js,argv[0]), js2number(js,argv[1]))))
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_mean,
|
|
|
|
|
JSC_CCALL(math_mean,
|
|
|
|
|
double len = js_arrlen(js,argv[0]);
|
|
|
|
|
double sum = 0;
|
|
|
|
|
for (int i = 0; i < len; i++)
|
|
|
|
|
@@ -1993,7 +2168,7 @@ JSC_CCALL(vector_mean,
|
|
|
|
|
return number2js(js,sum/len);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_sum,
|
|
|
|
|
JSC_CCALL(math_sum,
|
|
|
|
|
double sum = 0.0;
|
|
|
|
|
int len = js_arrlen(js,argv[0]);
|
|
|
|
|
for (int i = 0; i < len; i++)
|
|
|
|
|
@@ -2002,15 +2177,7 @@ JSC_CCALL(vector_sum,
|
|
|
|
|
return number2js(js,sum);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_fastsum,
|
|
|
|
|
float sum = 0.0;
|
|
|
|
|
// size_t len;
|
|
|
|
|
// float *a = get_typed_buffer(js, argv[0], &len);
|
|
|
|
|
// sum = cblas_sasum(len, a,1);
|
|
|
|
|
ret = number2js(js,sum);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_sigma,
|
|
|
|
|
JSC_CCALL(math_sigma,
|
|
|
|
|
int len = js_arrlen(js,argv[0]);
|
|
|
|
|
double sum = 0;
|
|
|
|
|
for (int i = 0; i < len; i++)
|
|
|
|
|
@@ -2030,7 +2197,7 @@ JSC_CCALL(vector_sigma,
|
|
|
|
|
return number2js(js,sqrt(variance));
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_median,
|
|
|
|
|
JSC_CCALL(math_median,
|
|
|
|
|
int len = js_arrlen(js,argv[0]);
|
|
|
|
|
double arr[len];
|
|
|
|
|
double temp;
|
|
|
|
|
@@ -2052,16 +2219,7 @@ JSC_CCALL(vector_median,
|
|
|
|
|
return number2js(js,arr[len/2]);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
int fibonacci(int n) {
|
|
|
|
|
if (n <= 1) return n;
|
|
|
|
|
return fibonacci(n-1) + fibonacci(n-2);
|
|
|
|
|
}
|
|
|
|
|
JSC_CCALL(vector_fib,
|
|
|
|
|
int n = js2number(js,argv[0]);
|
|
|
|
|
int fib = fibonacci(n);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_from_to,
|
|
|
|
|
JSC_CCALL(math_from_to,
|
|
|
|
|
HMM_Vec2 from = js2vec2(js,argv[0]);
|
|
|
|
|
HMM_Vec2 to = js2vec2(js,argv[1]);
|
|
|
|
|
float space = js2number(js,argv[2]);
|
|
|
|
|
@@ -2084,46 +2242,165 @@ JSC_CCALL(vector_from_to,
|
|
|
|
|
JS_SetPropertyUint32(js, ret, steps+1, vec22js(js,to));
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(vector_float32add,
|
|
|
|
|
size_t len;
|
|
|
|
|
float *vec_a = get_typed_buffer(js,self, &len);
|
|
|
|
|
// float *vec_b = get_typed_buffer(js,argv[0], &len);
|
|
|
|
|
// cblas_saxpy(len,1.0f,vec_b,1,vec_a,1);
|
|
|
|
|
JSValue tstack[3];
|
|
|
|
|
tstack[0] = JS_NewArrayBufferCopy(js,vec_a,sizeof(float)*4);
|
|
|
|
|
tstack[1] = JS_UNDEFINED;
|
|
|
|
|
tstack[2] = JS_UNDEFINED;
|
|
|
|
|
ret = JS_NewTypedArray(js, 3, tstack, JS_TYPED_ARRAY_FLOAT32);
|
|
|
|
|
JS_FreeValue(js,tstack[0]);
|
|
|
|
|
JSC_CCALL(math_rand, return JS_NewFloat64(js, genRand(&mrand)))
|
|
|
|
|
JSC_CCALL(math_randi, return JS_NewUint32(js, genRandLong(&mrand)))
|
|
|
|
|
JSC_CCALL(math_srand,
|
|
|
|
|
if (argc < 1)
|
|
|
|
|
m_seedRand(&mrand, time(NULL));
|
|
|
|
|
else
|
|
|
|
|
m_seedRand(&mrand, js2number(js,argv[0]));
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
static const JSCFunctionListEntry js_vector_funcs[] = {
|
|
|
|
|
MIST_FUNC_DEF(vector, dot,2),
|
|
|
|
|
MIST_FUNC_DEF(vector, project,2),
|
|
|
|
|
MIST_FUNC_DEF(vector, inflate, 2),
|
|
|
|
|
MIST_FUNC_DEF(vector, rotate, 3),
|
|
|
|
|
MIST_FUNC_DEF(vector, add, 2),
|
|
|
|
|
MIST_FUNC_DEF(vector, midpoint, 2),
|
|
|
|
|
MIST_FUNC_DEF(vector, distance, 2),
|
|
|
|
|
MIST_FUNC_DEF(vector, angle, 1),
|
|
|
|
|
MIST_FUNC_DEF(vector, norm, 1),
|
|
|
|
|
MIST_FUNC_DEF(vector, angle_between, 2),
|
|
|
|
|
MIST_FUNC_DEF(vector, lerp, 3),
|
|
|
|
|
MIST_FUNC_DEF(vector, gcd, 2),
|
|
|
|
|
MIST_FUNC_DEF(vector, lcm, 2),
|
|
|
|
|
MIST_FUNC_DEF(vector, clamp, 3),
|
|
|
|
|
MIST_FUNC_DEF(vector, angledist, 2),
|
|
|
|
|
MIST_FUNC_DEF(vector, variate, 2),
|
|
|
|
|
MIST_FUNC_DEF(vector, random_range, 2),
|
|
|
|
|
MIST_FUNC_DEF(vector, mean, 1),
|
|
|
|
|
MIST_FUNC_DEF(vector, sum, 1),
|
|
|
|
|
MIST_FUNC_DEF(vector, fastsum, 1),
|
|
|
|
|
MIST_FUNC_DEF(vector, sigma, 1),
|
|
|
|
|
MIST_FUNC_DEF(vector, median, 1),
|
|
|
|
|
MIST_FUNC_DEF(vector, length, 1),
|
|
|
|
|
MIST_FUNC_DEF(vector, fib, 1),
|
|
|
|
|
MIST_FUNC_DEF(vector, from_to, 5),
|
|
|
|
|
MIST_FUNC_DEF(vector, float32add, 2),
|
|
|
|
|
JSValue js_math_direction(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
|
|
|
|
size_t alen, blen;
|
|
|
|
|
float *a = js2floats(js, argv[0], &alen);
|
|
|
|
|
float *b = js2floats(js, argv[1], &blen);
|
|
|
|
|
|
|
|
|
|
if (!a || !b) {
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t len = (alen < blen) ? alen : blen;
|
|
|
|
|
if (len == 0) {
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float *dir = (float*)malloc(sizeof(float) * len);
|
|
|
|
|
if (!dir) {
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return JS_EXCEPTION; // or some error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compute (b - a)
|
|
|
|
|
for (size_t i = 0; i < len; i++)
|
|
|
|
|
dir[i] = b[i] - a[i];
|
|
|
|
|
|
|
|
|
|
// Compute magnitude of dir
|
|
|
|
|
float mag = 0.0f;
|
|
|
|
|
for (size_t i = 0; i < len; i++)
|
|
|
|
|
mag += dir[i] * dir[i];
|
|
|
|
|
mag = sqrtf(mag);
|
|
|
|
|
|
|
|
|
|
// Normalize if possible
|
|
|
|
|
if (mag > 0.0f) {
|
|
|
|
|
for (size_t i = 0; i < len; i++)
|
|
|
|
|
dir[i] /= mag;
|
|
|
|
|
} else {
|
|
|
|
|
// Optional: if a == b, direction is zero
|
|
|
|
|
// you might want to do something else here
|
|
|
|
|
// (like return all zeros).
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JSValue ret = floats2array(js, dir, len);
|
|
|
|
|
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
free(dir);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JSValue js_math_reflect(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
|
|
|
|
size_t vlen, nlen;
|
|
|
|
|
float *vec = js2floats(js, argv[0], &vlen);
|
|
|
|
|
float *norm = js2floats(js, argv[1], &nlen);
|
|
|
|
|
|
|
|
|
|
if (!vec || !norm) {
|
|
|
|
|
free(vec);
|
|
|
|
|
free(norm);
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t len = (vlen < nlen) ? vlen : nlen;
|
|
|
|
|
if (len == 0) {
|
|
|
|
|
free(vec);
|
|
|
|
|
free(norm);
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 1) Normalize the planeNormal
|
|
|
|
|
// p = planeNormal / |planeNormal|
|
|
|
|
|
float mag = 0.0f;
|
|
|
|
|
for (size_t i = 0; i < len; i++)
|
|
|
|
|
mag += norm[i] * norm[i];
|
|
|
|
|
mag = sqrtf(mag);
|
|
|
|
|
|
|
|
|
|
// If the plane normal is zero-length, no reflection is well-defined
|
|
|
|
|
if (mag == 0.0f) {
|
|
|
|
|
// Return original vec or undefined, your choice.
|
|
|
|
|
// Here, let's just return a copy of the original vec.
|
|
|
|
|
JSValue retNoReflect = floats2array(js, vec, vlen);
|
|
|
|
|
free(vec);
|
|
|
|
|
free(norm);
|
|
|
|
|
return retNoReflect;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float *pnorm = (float*)malloc(sizeof(float) * len);
|
|
|
|
|
if (!pnorm) {
|
|
|
|
|
free(vec);
|
|
|
|
|
free(norm);
|
|
|
|
|
return JS_EXCEPTION;
|
|
|
|
|
}
|
|
|
|
|
for (size_t i = 0; i < len; i++)
|
|
|
|
|
pnorm[i] = norm[i] / mag;
|
|
|
|
|
|
|
|
|
|
// 2) Compute dot = vec•pnorm
|
|
|
|
|
float dot = 0.0f;
|
|
|
|
|
for (size_t i = 0; i < len; i++)
|
|
|
|
|
dot += vec[i] * pnorm[i];
|
|
|
|
|
|
|
|
|
|
// 3) reflect = vec - 2*dot*pnorm
|
|
|
|
|
float *ref = (float*)malloc(sizeof(float) * len);
|
|
|
|
|
if (!ref) {
|
|
|
|
|
free(vec);
|
|
|
|
|
free(norm);
|
|
|
|
|
free(pnorm);
|
|
|
|
|
return JS_EXCEPTION;
|
|
|
|
|
}
|
|
|
|
|
for (size_t i = 0; i < len; i++)
|
|
|
|
|
ref[i] = vec[i] - 2.0f * dot * pnorm[i];
|
|
|
|
|
|
|
|
|
|
// Now return 'ref' as an array
|
|
|
|
|
JSValue ret = floats2array(js, ref, len);
|
|
|
|
|
|
|
|
|
|
free(vec);
|
|
|
|
|
free(norm);
|
|
|
|
|
free(pnorm);
|
|
|
|
|
free(ref);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const JSCFunctionListEntry js_math_funcs[] = {
|
|
|
|
|
MIST_FUNC_DEF(math, dot,2),
|
|
|
|
|
MIST_FUNC_DEF(math, project,2),
|
|
|
|
|
MIST_FUNC_DEF(math, rotate, 3),
|
|
|
|
|
MIST_FUNC_DEF(math, midpoint, 2),
|
|
|
|
|
MIST_FUNC_DEF(math, reflect, 0),
|
|
|
|
|
MIST_FUNC_DEF(math, distance, 2),
|
|
|
|
|
MIST_FUNC_DEF(math, direction, 2),
|
|
|
|
|
MIST_FUNC_DEF(math, angle, 1),
|
|
|
|
|
MIST_FUNC_DEF(math, norm, 1),
|
|
|
|
|
MIST_FUNC_DEF(math, angle_between, 2),
|
|
|
|
|
MIST_FUNC_DEF(math, lerp, 3),
|
|
|
|
|
MIST_FUNC_DEF(math, gcd, 2),
|
|
|
|
|
MIST_FUNC_DEF(math, lcm, 2),
|
|
|
|
|
MIST_FUNC_DEF(math, clamp, 3),
|
|
|
|
|
MIST_FUNC_DEF(math, angledist, 2),
|
|
|
|
|
MIST_FUNC_DEF(math, jitter, 2),
|
|
|
|
|
MIST_FUNC_DEF(math, mean, 1),
|
|
|
|
|
MIST_FUNC_DEF(math, sum, 1),
|
|
|
|
|
MIST_FUNC_DEF(math, sigma, 1),
|
|
|
|
|
MIST_FUNC_DEF(math, median, 1),
|
|
|
|
|
MIST_FUNC_DEF(math, length, 1),
|
|
|
|
|
MIST_FUNC_DEF(math, from_to, 5),
|
|
|
|
|
MIST_FUNC_DEF(math, rand, 0),
|
|
|
|
|
MIST_FUNC_DEF(math, randi, 0),
|
|
|
|
|
MIST_FUNC_DEF(math, srand,0),
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define JS_HMM_FN(OP, HMM, SIGN) \
|
|
|
|
|
@@ -2154,53 +2431,6 @@ JSC_CCALL(array_##OP, \
|
|
|
|
|
return arr; \
|
|
|
|
|
) \
|
|
|
|
|
|
|
|
|
|
/*JSC_CCALL(array_add,
|
|
|
|
|
int len = js_arrlen(js,self);
|
|
|
|
|
if (!JS_IsArray(js, argv[0])) {
|
|
|
|
|
double n = js2number(js,argv[0]);
|
|
|
|
|
JSValue arr = JS_NewArray(js);
|
|
|
|
|
for (int i = 0; i < len; i++)
|
|
|
|
|
JS_SetPropertyUint32(js, arr, i, number2js(js,js_getnum_uint32(js, self,i) + n));
|
|
|
|
|
return arr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JSValue arr = JS_NewArray(js);
|
|
|
|
|
size_t len_a, len_b;
|
|
|
|
|
float *a = js2floats(js,self, &len_a);
|
|
|
|
|
float *b = js2floats(js,argv[0], &len_b);
|
|
|
|
|
cblas_saxpy(len_a, 1.0, a, 1, b, 1);
|
|
|
|
|
for (int i = 0; i < len; i++)
|
|
|
|
|
JS_SetPropertyUint32(js, arr, i, number2js(js,b[i]));
|
|
|
|
|
|
|
|
|
|
ret = arr;
|
|
|
|
|
free(a);
|
|
|
|
|
free(b);
|
|
|
|
|
return arr;
|
|
|
|
|
) */
|
|
|
|
|
|
|
|
|
|
/*JSC_CCALL(array_add,
|
|
|
|
|
int len = js_arrlen(js,self);
|
|
|
|
|
if (!JS_IsArray(js,argv[0])) {
|
|
|
|
|
double n = js2number(js,argv[0]);
|
|
|
|
|
JSValue arr = JS_NewArray(js);
|
|
|
|
|
for (int i = 0; i < len; i++)
|
|
|
|
|
JS_SetPropertyUint32(js,arr,i,number2js(js,js_getnum_uint32(js,self,i) + n));
|
|
|
|
|
|
|
|
|
|
return arr;
|
|
|
|
|
}
|
|
|
|
|
float *vec_a = js2floatarray(js,self);
|
|
|
|
|
float *vec_b = js2floatarray(js,argv[0]);
|
|
|
|
|
cblas_saxpy(len,1.0f,vec_b,1,vec_a,1);
|
|
|
|
|
JSValue tstack[3];
|
|
|
|
|
tstack[0] = JS_NewArrayBuffer(js,vec_a,sizeof(float)*2,free_gpu_buffer, NULL, 0);
|
|
|
|
|
tstack[1] = JS_UNDEFINED;
|
|
|
|
|
tstack[2] = JS_UNDEFINED;
|
|
|
|
|
ret = JS_NewTypedArray(js, 3, tstack, JS_TYPED_ARRAY_FLOAT32);
|
|
|
|
|
JS_FreeValue(js,tstack[0]);
|
|
|
|
|
free(vec_b);
|
|
|
|
|
)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
JS_HMM_FN(add, Add, +)
|
|
|
|
|
JS_HMM_FN(sub, Sub, -)
|
|
|
|
|
JS_HMM_FN(div, Div, /)
|
|
|
|
|
@@ -7300,13 +7530,9 @@ static ModuleEntry module_registry[] = {
|
|
|
|
|
MISTLINE(os),
|
|
|
|
|
MISTLINE(input),
|
|
|
|
|
MISTLINE(time),
|
|
|
|
|
// MISTLINE(profile),
|
|
|
|
|
// MISTLINE(debug),
|
|
|
|
|
MISTLINE(vector),
|
|
|
|
|
MISTLINE(math),
|
|
|
|
|
MISTLINE(spline),
|
|
|
|
|
// MISTLINE(performance),
|
|
|
|
|
MISTLINE(geometry),
|
|
|
|
|
// MISTLINE(camera),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
JSC_SCALL(os_use_embed,
|
|
|
|
|
@@ -7780,5 +8006,7 @@ void ffi_load(JSContext *js) {
|
|
|
|
|
signal(SIGABRT, signal_handler);
|
|
|
|
|
atexit(exit_handler);
|
|
|
|
|
|
|
|
|
|
m_seedRand(&mrand, time(NULL));
|
|
|
|
|
|
|
|
|
|
JS_FreeValue(js,globalThis);
|
|
|
|
|
}
|
|
|
|
|
|