diff options
author | bellard <6490144+bellard@users.noreply.github.com> | 2020-09-06 18:53:08 +0200 |
---|---|---|
committer | bellard <6490144+bellard@users.noreply.github.com> | 2020-09-06 18:53:08 +0200 |
commit | 91459fb6723e29e923380cec0023af93819ae69d (patch) | |
tree | 6a1aff8d9b290ed184d1481da50d0e6b4a9a324c /examples | |
parent | 9096e544ba2357eeadc6f09fc6e5cf58db7751bc (diff) | |
download | quickjs-91459fb6723e29e923380cec0023af93819ae69d.tar.gz quickjs-91459fb6723e29e923380cec0023af93819ae69d.zip |
2020-01-05 release
Diffstat (limited to 'examples')
-rw-r--r-- | examples/fib.c | 72 | ||||
-rw-r--r-- | examples/fib_module.js | 10 | ||||
-rw-r--r-- | examples/hello.js | 1 | ||||
-rw-r--r-- | examples/hello_module.js | 6 | ||||
-rw-r--r-- | examples/pi_bigdecimal.js | 70 | ||||
-rw-r--r-- | examples/pi_bigfloat.js | 66 | ||||
-rw-r--r-- | examples/pi_bigint.js | 118 | ||||
-rw-r--r-- | examples/point.c | 151 | ||||
-rw-r--r-- | examples/test_fib.js | 6 | ||||
-rw-r--r-- | examples/test_point.js | 40 |
10 files changed, 540 insertions, 0 deletions
diff --git a/examples/fib.c b/examples/fib.c new file mode 100644 index 0000000..c77b705 --- /dev/null +++ b/examples/fib.c @@ -0,0 +1,72 @@ +/* + * QuickJS: Example of C module + * + * Copyright (c) 2017-2018 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "../quickjs.h" + +#define countof(x) (sizeof(x) / sizeof((x)[0])) + +static int fib(int n) +{ + if (n <= 0) + return 0; + else if (n == 1) + return 1; + else + return fib(n - 1) + fib(n - 2); +} + +static JSValue js_fib(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + int n, res; + if (JS_ToInt32(ctx, &n, argv[0])) + return JS_EXCEPTION; + res = fib(n); + return JS_NewInt32(ctx, res); +} + +static const JSCFunctionListEntry js_fib_funcs[] = { + JS_CFUNC_DEF("fib", 1, js_fib ), +}; + +static int js_fib_init(JSContext *ctx, JSModuleDef *m) +{ + return JS_SetModuleExportList(ctx, m, js_fib_funcs, + countof(js_fib_funcs)); +} + +#ifdef JS_SHARED_LIBRARY +#define JS_INIT_MODULE js_init_module +#else +#define JS_INIT_MODULE js_init_module_fib +#endif + +JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) +{ + JSModuleDef *m; + m = JS_NewCModule(ctx, module_name, js_fib_init); + if (!m) + return NULL; + JS_AddModuleExportList(ctx, m, js_fib_funcs, countof(js_fib_funcs)); + return m; +} diff --git a/examples/fib_module.js b/examples/fib_module.js new file mode 100644 index 0000000..6a81071 --- /dev/null +++ b/examples/fib_module.js @@ -0,0 +1,10 @@ +/* fib module */ +export function fib(n) +{ + if (n <= 0) + return 0; + else if (n == 1) + return 1; + else + return fib(n - 1) + fib(n - 2); +} diff --git a/examples/hello.js b/examples/hello.js new file mode 100644 index 0000000..accefce --- /dev/null +++ b/examples/hello.js @@ -0,0 +1 @@ +console.log("Hello World"); diff --git a/examples/hello_module.js b/examples/hello_module.js new file mode 100644 index 0000000..463660f --- /dev/null +++ b/examples/hello_module.js @@ -0,0 +1,6 @@ +/* example of JS module */ + +import { fib } from "./fib_module.js"; + +console.log("Hello World"); +console.log("fib(10)=", fib(10)); diff --git a/examples/pi_bigdecimal.js b/examples/pi_bigdecimal.js new file mode 100644 index 0000000..7d5eccf --- /dev/null +++ b/examples/pi_bigdecimal.js @@ -0,0 +1,70 @@ +/* + * PI computation in Javascript using the QuickJS bigdecimal type + * (decimal floating point) + */ +"use strict"; + +/* compute PI with a precision of 'prec' digits */ +function calc_pi(prec) { + const CHUD_A = 13591409d; + const CHUD_B = 545140134d; + const CHUD_C = 640320d; + const CHUD_C3 = 10939058860032000d; /* C^3/24 */ + const CHUD_DIGITS_PER_TERM = 14.18164746272548; /* log10(C/12)*3 */ + + /* return [P, Q, G] */ + function chud_bs(a, b, need_G) { + var c, P, Q, G, P1, Q1, G1, P2, Q2, G2, b1; + if (a == (b - 1n)) { + b1 = BigDecimal(b); + G = (2d * b1 - 1d) * (6d * b1 - 1d) * (6d * b1 - 5d); + P = G * (CHUD_B * b1 + CHUD_A); + if (b & 1n) + P = -P; + G = G; + Q = b1 * b1 * b1 * CHUD_C3; + } else { + c = (a + b) >> 1n; + [P1, Q1, G1] = chud_bs(a, c, true); + [P2, Q2, G2] = chud_bs(c, b, need_G); + P = P1 * Q2 + P2 * G1; + Q = Q1 * Q2; + if (need_G) + G = G1 * G2; + else + G = 0d; + } + return [P, Q, G]; + } + + var n, P, Q, G; + /* number of serie terms */ + n = BigInt(Math.ceil(prec / CHUD_DIGITS_PER_TERM)) + 10n; + [P, Q, G] = chud_bs(0n, n, false); + Q = BigDecimal.div(Q, (P + Q * CHUD_A), + { roundingMode: "half-even", + maximumSignificantDigits: prec }); + G = (CHUD_C / 12d) * BigDecimal.sqrt(CHUD_C, + { roundingMode: "half-even", + maximumSignificantDigits: prec }); + return Q * G; +} + +(function() { + var r, n_digits, n_bits; + if (typeof scriptArgs != "undefined") { + if (scriptArgs.length < 2) { + print("usage: pi n_digits"); + return; + } + n_digits = scriptArgs[1] | 0; + } else { + n_digits = 1000; + } + /* we add more digits to reduce the probability of bad rounding for + the last digits */ + r = calc_pi(n_digits + 20); + r = BigDecimal.round(r, { roundingMode: "down", + maximumFractionDigits: n_digits }) + print(r); +})(); diff --git a/examples/pi_bigfloat.js b/examples/pi_bigfloat.js new file mode 100644 index 0000000..2bcda22 --- /dev/null +++ b/examples/pi_bigfloat.js @@ -0,0 +1,66 @@ +/* + * PI computation in Javascript using the QuickJS bigfloat type + * (binary floating point) + */ +"use strict"; + +/* compute PI with a precision of 'prec' bits */ +function calc_pi() { + const CHUD_A = 13591409n; + const CHUD_B = 545140134n; + const CHUD_C = 640320n; + const CHUD_C3 = 10939058860032000n; /* C^3/24 */ + const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */ + + /* return [P, Q, G] */ + function chud_bs(a, b, need_G) { + var c, P, Q, G, P1, Q1, G1, P2, Q2, G2; + if (a == (b - 1n)) { + G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n); + P = BigFloat(G * (CHUD_B * b + CHUD_A)); + if (b & 1n) + P = -P; + G = BigFloat(G); + Q = BigFloat(b * b * b * CHUD_C3); + } else { + c = (a + b) >> 1n; + [P1, Q1, G1] = chud_bs(a, c, true); + [P2, Q2, G2] = chud_bs(c, b, need_G); + P = P1 * Q2 + P2 * G1; + Q = Q1 * Q2; + if (need_G) + G = G1 * G2; + else + G = 0l; + } + return [P, Q, G]; + } + + var n, P, Q, G; + /* number of serie terms */ + n = BigInt(Math.ceil(BigFloatEnv.prec / CHUD_BITS_PER_TERM)) + 10n; + [P, Q, G] = chud_bs(0n, n, false); + Q = Q / (P + Q * BigFloat(CHUD_A)); + G = BigFloat((CHUD_C / 12n)) * BigFloat.sqrt(BigFloat(CHUD_C)); + return Q * G; +} + +(function() { + var r, n_digits, n_bits; + if (typeof scriptArgs != "undefined") { + if (scriptArgs.length < 2) { + print("usage: pi n_digits"); + return; + } + n_digits = scriptArgs[1]; + } else { + n_digits = 1000; + } + n_bits = Math.ceil(n_digits * Math.log2(10)); + /* we add more bits to reduce the probability of bad rounding for + the last digits */ + BigFloatEnv.setPrec( () => { + r = calc_pi(); + print(r.toFixed(n_digits, BigFloatEnv.RNDZ)); + }, n_bits + 32); +})(); diff --git a/examples/pi_bigint.js b/examples/pi_bigint.js new file mode 100644 index 0000000..cbbb2c4 --- /dev/null +++ b/examples/pi_bigint.js @@ -0,0 +1,118 @@ +/* + * PI computation in Javascript using the BigInt type + */ +"use strict"; + +/* return floor(log2(a)) for a > 0 and 0 for a = 0 */ +function floor_log2(a) +{ + var k_max, a1, k, i; + k_max = 0n; + while ((a >> (2n ** k_max)) != 0n) { + k_max++; + } + k = 0n; + a1 = a; + for(i = k_max - 1n; i >= 0n; i--) { + a1 = a >> (2n ** i); + if (a1 != 0n) { + a = a1; + k |= (1n << i); + } + } + return k; +} + +/* return ceil(log2(a)) for a > 0 */ +function ceil_log2(a) +{ + return floor_log2(a - 1n) + 1n; +} + +/* return floor(sqrt(a)) (not efficient but simple) */ +function int_sqrt(a) +{ + var l, u, s; + if (a == 0n) + return a; + l = ceil_log2(a); + u = 1n << ((l + 1n) / 2n); + /* u >= floor(sqrt(a)) */ + for(;;) { + s = u; + u = ((a / s) + s) / 2n; + if (u >= s) + break; + } + return s; +} + +/* return pi * 2**prec */ +function calc_pi(prec) { + const CHUD_A = 13591409n; + const CHUD_B = 545140134n; + const CHUD_C = 640320n; + const CHUD_C3 = 10939058860032000n; /* C^3/24 */ + const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */ + + /* return [P, Q, G] */ + function chud_bs(a, b, need_G) { + var c, P, Q, G, P1, Q1, G1, P2, Q2, G2; + if (a == (b - 1n)) { + G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n); + P = G * (CHUD_B * b + CHUD_A); + if (b & 1n) + P = -P; + Q = b * b * b * CHUD_C3; + } else { + c = (a + b) >> 1n; + [P1, Q1, G1] = chud_bs(a, c, true); + [P2, Q2, G2] = chud_bs(c, b, need_G); + P = P1 * Q2 + P2 * G1; + Q = Q1 * Q2; + if (need_G) + G = G1 * G2; + else + G = 0n; + } + return [P, Q, G]; + } + + var n, P, Q, G; + /* number of serie terms */ + n = BigInt(Math.ceil(Number(prec) / CHUD_BITS_PER_TERM)) + 10n; + [P, Q, G] = chud_bs(0n, n, false); + Q = (CHUD_C / 12n) * (Q << prec) / (P + Q * CHUD_A); + G = int_sqrt(CHUD_C << (2n * prec)); + return (Q * G) >> prec; +} + +function main(args) { + var r, n_digits, n_bits, out; + if (args.length < 1) { + print("usage: pi n_digits"); + return; + } + n_digits = args[0] | 0; + + /* we add more bits to reduce the probability of bad rounding for + the last digits */ + n_bits = BigInt(Math.ceil(n_digits * Math.log2(10))) + 32n; + r = calc_pi(n_bits); + r = ((10n ** BigInt(n_digits)) * r) >> n_bits; + out = r.toString(); + print(out[0] + "." + out.slice(1)); +} + +var args; +if (typeof scriptArgs != "undefined") { + args = scriptArgs; + args.shift(); +} else if (typeof arguments != "undefined") { + args = arguments; +} else { + /* default: 1000 digits */ + args=[1000]; +} + +main(args); diff --git a/examples/point.c b/examples/point.c new file mode 100644 index 0000000..049d135 --- /dev/null +++ b/examples/point.c @@ -0,0 +1,151 @@ +/* + * QuickJS: Example of C module with a class + * + * Copyright (c) 2019 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "../quickjs.h" +#include <math.h> + +#define countof(x) (sizeof(x) / sizeof((x)[0])) + +/* Point Class */ + +typedef struct { + int x; + int y; +} JSPointData; + +static JSClassID js_point_class_id; + +static void js_point_finalizer(JSRuntime *rt, JSValue val) +{ + JSPointData *s = JS_GetOpaque(val, js_point_class_id); + /* Note: 's' can be NULL in case JS_SetOpaque() was not called */ + js_free_rt(rt, s); +} + +static JSValue js_point_ctor(JSContext *ctx, + JSValueConst new_target, + int argc, JSValueConst *argv) +{ + JSPointData *s; + JSValue obj = JS_UNDEFINED; + JSValue proto; + + s = js_mallocz(ctx, sizeof(*s)); + if (!s) + return JS_EXCEPTION; + if (JS_ToInt32(ctx, &s->x, argv[0])) + goto fail; + if (JS_ToInt32(ctx, &s->y, argv[1])) + goto fail; + /* using new_target to get the prototype is necessary when the + class is extended. */ + proto = JS_GetPropertyStr(ctx, new_target, "prototype"); + if (JS_IsException(proto)) + goto fail; + obj = JS_NewObjectProtoClass(ctx, proto, js_point_class_id); + JS_FreeValue(ctx, proto); + if (JS_IsException(obj)) + goto fail; + JS_SetOpaque(obj, s); + return obj; + fail: + js_free(ctx, s); + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; +} + +static JSValue js_point_get_xy(JSContext *ctx, JSValueConst this_val, int magic) +{ + JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); + if (!s) + return JS_EXCEPTION; + if (magic == 0) + return JS_NewInt32(ctx, s->x); + else + return JS_NewInt32(ctx, s->y); +} + +static JSValue js_point_set_xy(JSContext *ctx, JSValueConst this_val, JSValue val, int magic) +{ + JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); + int v; + if (!s) + return JS_EXCEPTION; + if (JS_ToInt32(ctx, &v, val)) + return JS_EXCEPTION; + if (magic == 0) + s->x = v; + else + s->y = v; + return JS_UNDEFINED; +} + +static JSValue js_point_norm(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); + if (!s) + return JS_EXCEPTION; + return JS_NewFloat64(ctx, sqrt((double)s->x * s->x + (double)s->y * s->y)); +} + +static JSClassDef js_point_class = { + "Point", + .finalizer = js_point_finalizer, +}; + +static const JSCFunctionListEntry js_point_proto_funcs[] = { + JS_CGETSET_MAGIC_DEF("x", js_point_get_xy, js_point_set_xy, 0), + JS_CGETSET_MAGIC_DEF("y", js_point_get_xy, js_point_set_xy, 1), + JS_CFUNC_DEF("norm", 0, js_point_norm), +}; + +static int js_point_init(JSContext *ctx, JSModuleDef *m) +{ + JSValue point_proto, point_class; + + /* create the Point class */ + JS_NewClassID(&js_point_class_id); + JS_NewClass(JS_GetRuntime(ctx), js_point_class_id, &js_point_class); + + point_proto = JS_NewObject(ctx); + JS_SetPropertyFunctionList(ctx, point_proto, js_point_proto_funcs, countof(js_point_proto_funcs)); + JS_SetClassProto(ctx, js_point_class_id, point_proto); + + point_class = JS_NewCFunction2(ctx, js_point_ctor, "Point", 2, JS_CFUNC_constructor, 0); + /* set proto.constructor and ctor.prototype */ + JS_SetConstructor(ctx, point_class, point_proto); + + JS_SetModuleExport(ctx, m, "Point", point_class); + return 0; +} + +JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) +{ + JSModuleDef *m; + m = JS_NewCModule(ctx, module_name, js_point_init); + if (!m) + return NULL; + JS_AddModuleExport(ctx, m, "Point"); + return m; +} diff --git a/examples/test_fib.js b/examples/test_fib.js new file mode 100644 index 0000000..70d26bd --- /dev/null +++ b/examples/test_fib.js @@ -0,0 +1,6 @@ +/* example of JS module importing a C module */ + +import { fib } from "./fib.so"; + +console.log("Hello World"); +console.log("fib(10)=", fib(10)); diff --git a/examples/test_point.js b/examples/test_point.js new file mode 100644 index 0000000..0659bc3 --- /dev/null +++ b/examples/test_point.js @@ -0,0 +1,40 @@ +/* example of JS module importing a C module */ +import { Point } from "./point.so"; + +function assert(b, str) +{ + if (b) { + return; + } else { + throw Error("assertion failed: " + str); + } +} + +class ColorPoint extends Point { + constructor(x, y, color) { + super(x, y); + this.color = color; + } + get_color() { + return this.color; + } +}; + +function main() +{ + var pt, pt2; + + pt = new Point(2, 3); + assert(pt.x === 2); + assert(pt.y === 3); + pt.x = 4; + assert(pt.x === 4); + assert(pt.norm() == 5); + + pt2 = new ColorPoint(2, 3, 0xffffff); + assert(pt2.x === 2); + assert(pt2.color === 0xffffff); + assert(pt2.get_color() === 0xffffff); +} + +main(); |