Merge branch 'improve_compile_error'
This commit is contained in:
50
src/cell_math.c
Normal file
50
src/cell_math.c
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "cell_math.h"
|
||||
#include <math.h>
|
||||
|
||||
JSValue js_math_e (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
||||
double power = 1.0;
|
||||
if (argc > 0 && !JS_IsNull (argv[0])) {
|
||||
if (JS_ToFloat64 (ctx, &power, argv[0]) < 0) return JS_EXCEPTION;
|
||||
}
|
||||
return JS_NewFloat64 (ctx, exp (power));
|
||||
}
|
||||
|
||||
JSValue js_math_ln (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
||||
double x;
|
||||
if (JS_ToFloat64 (ctx, &x, argv[0]) < 0) return JS_EXCEPTION;
|
||||
return JS_NewFloat64 (ctx, log (x));
|
||||
}
|
||||
|
||||
JSValue js_math_log10 (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
||||
double x;
|
||||
if (JS_ToFloat64 (ctx, &x, argv[0]) < 0) return JS_EXCEPTION;
|
||||
return JS_NewFloat64 (ctx, log10 (x));
|
||||
}
|
||||
|
||||
JSValue js_math_log2 (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
||||
double x;
|
||||
if (JS_ToFloat64 (ctx, &x, argv[0]) < 0) return JS_EXCEPTION;
|
||||
return JS_NewFloat64 (ctx, log2 (x));
|
||||
}
|
||||
|
||||
JSValue js_math_power (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
||||
double x, y;
|
||||
if (argc < 2) return JS_NULL;
|
||||
if (JS_ToFloat64 (ctx, &x, argv[0]) < 0) return JS_EXCEPTION;
|
||||
if (JS_ToFloat64 (ctx, &y, argv[1]) < 0) return JS_EXCEPTION;
|
||||
return JS_NewFloat64 (ctx, pow (x, y));
|
||||
}
|
||||
|
||||
JSValue js_math_root (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
||||
double x, n;
|
||||
if (argc < 2) return JS_NULL;
|
||||
if (JS_ToFloat64 (ctx, &x, argv[0]) < 0) return JS_EXCEPTION;
|
||||
if (JS_ToFloat64 (ctx, &n, argv[1]) < 0) return JS_EXCEPTION;
|
||||
return JS_NewFloat64 (ctx, pow (x, 1.0 / n));
|
||||
}
|
||||
|
||||
JSValue js_math_sqrt (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
||||
double x;
|
||||
if (JS_ToFloat64 (ctx, &x, argv[0]) < 0) return JS_EXCEPTION;
|
||||
return JS_NewFloat64 (ctx, sqrt (x));
|
||||
}
|
||||
14
src/cell_math.h
Normal file
14
src/cell_math.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef CELL_MATH_H
|
||||
#define CELL_MATH_H
|
||||
|
||||
#include "cell.h"
|
||||
|
||||
JSValue js_math_e (JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
|
||||
JSValue js_math_ln (JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
|
||||
JSValue js_math_log10 (JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
|
||||
JSValue js_math_log2 (JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
|
||||
JSValue js_math_power (JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
|
||||
JSValue js_math_root (JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
|
||||
JSValue js_math_sqrt (JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
|
||||
|
||||
#endif
|
||||
93
src/fash.c
Normal file
93
src/fash.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Fash64: Douglas Crockford (2017-02-02)
|
||||
64-bit hash that uses the high 64 bits of a 128-bit product for feedback.
|
||||
|
||||
Notes:
|
||||
- Requires a way to get the high half of a 64x64->128 multiply.
|
||||
- Uses __uint128_t when available; otherwise uses MSVC _umul128.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct fash64_state {
|
||||
uint64_t result;
|
||||
uint64_t sum;
|
||||
} fash64_state;
|
||||
|
||||
enum {
|
||||
FASH64_PRIME_11 = 11111111111111111027ull,
|
||||
FASH64_PRIME_8 = 8888888888888888881ull,
|
||||
FASH64_PRIME_3 = 3333333333333333271ull
|
||||
};
|
||||
|
||||
static inline void fash64_mul_hi_lo(uint64_t a, uint64_t b, uint64_t *hi, uint64_t *lo)
|
||||
{
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
__uint128_t p = (__uint128_t)a * (__uint128_t)b;
|
||||
*lo = (uint64_t)p;
|
||||
*hi = (uint64_t)(p >> 64);
|
||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
||||
*lo = _umul128(a, b, hi);
|
||||
#else
|
||||
/* Portable fallback (no 128-bit type, no _umul128). */
|
||||
uint64_t a0 = (uint32_t)a;
|
||||
uint64_t a1 = a >> 32;
|
||||
uint64_t b0 = (uint32_t)b;
|
||||
uint64_t b1 = b >> 32;
|
||||
|
||||
uint64_t p00 = a0 * b0;
|
||||
uint64_t p01 = a0 * b1;
|
||||
uint64_t p10 = a1 * b0;
|
||||
uint64_t p11 = a1 * b1;
|
||||
|
||||
uint64_t mid = (p00 >> 32) + (uint32_t)p01 + (uint32_t)p10;
|
||||
*lo = (p00 & 0xffffffffull) | (mid << 32);
|
||||
*hi = p11 + (p01 >> 32) + (p10 >> 32) + (mid >> 32);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void fash64_begin(fash64_state *s)
|
||||
{
|
||||
s->result = (uint64_t)FASH64_PRIME_8;
|
||||
s->sum = (uint64_t)FASH64_PRIME_3;
|
||||
}
|
||||
|
||||
static inline void fash64_word(fash64_state *s, uint64_t word)
|
||||
{
|
||||
uint64_t high, low;
|
||||
uint64_t mixed = s->result ^ word;
|
||||
|
||||
fash64_mul_hi_lo(mixed, (uint64_t)FASH64_PRIME_11, &high, &low);
|
||||
|
||||
s->sum += high;
|
||||
s->result = low ^ s->sum;
|
||||
}
|
||||
|
||||
static inline void fash64_block(fash64_state *s, const uint64_t *block, size_t word_count)
|
||||
{
|
||||
for (size_t i = 0; i < word_count; i++) fash64_word(s, block[i]);
|
||||
}
|
||||
|
||||
static inline uint64_t fash64_end(const fash64_state *s)
|
||||
{
|
||||
return s->result;
|
||||
}
|
||||
|
||||
/* Convenience one-shot helper */
|
||||
static inline uint64_t fash64_hash_words(const uint64_t *words, size_t word_count, uint64_t extra_word)
|
||||
{
|
||||
fash64_state s;
|
||||
fash64_begin(&s);
|
||||
fash64_block(&s, words, word_count);
|
||||
fash64_word(&s, extra_word);
|
||||
return fash64_end(&s);
|
||||
}
|
||||
|
||||
static inline uint64_t fash64_hash_one(uint64_t word)
|
||||
{
|
||||
uint64_t high, low;
|
||||
uint64_t mixed = (uint64_t)FASH64_PRIME_8 ^ word;
|
||||
fash64_mul_hi_lo(mixed, (uint64_t)FASH64_PRIME_11, &high, &low);
|
||||
return low ^ ((uint64_t)FASH64_PRIME_3 + high);
|
||||
}
|
||||
82
src/qbe_rt.c
Normal file
82
src/qbe_rt.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* qbe_rt.c - Non-inline wrappers for QBE-compiled ƿit modules
|
||||
*
|
||||
* Provides non-inline versions of static-inline quickjs functions
|
||||
* (which QBE-generated code calls as external symbols).
|
||||
*
|
||||
* All cell_rt_* runtime functions are implemented in source/qbe_helpers.c
|
||||
* (compiled into the cell binary) and resolved via -undefined dynamic_lookup.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef uint64_t JSValue;
|
||||
typedef struct JSContext JSContext;
|
||||
|
||||
#define JS_TAG_SHORT_FLOAT 5
|
||||
#define JS_TAG_NULL 7
|
||||
#define JS_VAL_NULL 7
|
||||
|
||||
/* ============================================================
|
||||
Non-inline wrappers for static-inline quickjs functions
|
||||
============================================================ */
|
||||
|
||||
/*
|
||||
* __JS_NewFloat64 — encode double as tagged JSValue
|
||||
* Short float: [sign:1][exp:8][mantissa:52][tag:3]
|
||||
* Returns tagged int if value is an exact integer in int32 range
|
||||
*/
|
||||
JSValue __JS_NewFloat64(JSContext *ctx, double d) {
|
||||
union { double d; uint64_t u; } u;
|
||||
u.d = d;
|
||||
|
||||
uint64_t sign = u.u >> 63;
|
||||
int exp = (u.u >> 52) & 0x7FF;
|
||||
uint64_t mantissa = u.u & ((1ULL << 52) - 1);
|
||||
|
||||
/* Zero */
|
||||
if (exp == 0 && mantissa == 0)
|
||||
return JS_TAG_SHORT_FLOAT;
|
||||
/* NaN/Inf → null */
|
||||
if (exp == 0x7FF)
|
||||
return JS_VAL_NULL;
|
||||
/* Subnormals → zero */
|
||||
if (exp == 0)
|
||||
return (sign << 63) | JS_TAG_SHORT_FLOAT;
|
||||
|
||||
int short_exp = exp - 1023 + 127;
|
||||
if (short_exp < 1 || short_exp > 254)
|
||||
return JS_VAL_NULL;
|
||||
|
||||
/* Prefer integer if exact */
|
||||
if (d >= (double)(-2147483647 - 1) && d <= (double)2147483647) {
|
||||
int32_t i = (int32_t)d;
|
||||
if ((double)i == d)
|
||||
return (uint64_t)(uint32_t)i << 1;
|
||||
}
|
||||
|
||||
return (sign << 63)
|
||||
| ((uint64_t)short_exp << 55)
|
||||
| (mantissa << 3)
|
||||
| JS_TAG_SHORT_FLOAT;
|
||||
}
|
||||
|
||||
/*
|
||||
* JS_IsNumber — check if value is tagged int or short float
|
||||
*/
|
||||
int JS_IsNumber(JSValue v) {
|
||||
int is_int = (v & 1) == 0;
|
||||
int is_float = (v & 7) == JS_TAG_SHORT_FLOAT;
|
||||
return is_int || is_float;
|
||||
}
|
||||
|
||||
/*
|
||||
* JS_NewString — create string from C string (wraps JS_NewStringLen)
|
||||
*/
|
||||
extern JSValue JS_NewStringLen(JSContext *ctx, const char *str, size_t len);
|
||||
|
||||
JSValue JS_NewString(JSContext *ctx, const char *str) {
|
||||
return JS_NewStringLen(ctx, str, strlen(str));
|
||||
}
|
||||
Reference in New Issue
Block a user