summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorbellard <6490144+bellard@users.noreply.github.com>2020-09-06 18:53:08 +0200
committerbellard <6490144+bellard@users.noreply.github.com>2020-09-06 18:53:08 +0200
commit91459fb6723e29e923380cec0023af93819ae69d (patch)
tree6a1aff8d9b290ed184d1481da50d0e6b4a9a324c /examples
parent9096e544ba2357eeadc6f09fc6e5cf58db7751bc (diff)
downloadquickjs-91459fb6723e29e923380cec0023af93819ae69d.tar.gz
quickjs-91459fb6723e29e923380cec0023af93819ae69d.zip
2020-01-05 release
Diffstat (limited to 'examples')
-rw-r--r--examples/fib.c72
-rw-r--r--examples/fib_module.js10
-rw-r--r--examples/hello.js1
-rw-r--r--examples/hello_module.js6
-rw-r--r--examples/pi_bigdecimal.js70
-rw-r--r--examples/pi_bigfloat.js66
-rw-r--r--examples/pi_bigint.js118
-rw-r--r--examples/point.c151
-rw-r--r--examples/test_fib.js6
-rw-r--r--examples/test_point.js40
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();