diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 0000000..3f40e55 --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,8 @@ + +.PHONY: all clean + +all: + make -C as-median build + +clean: + make -C as-median $@ diff --git a/examples/as-median/.gitignore b/examples/as-median/.gitignore new file mode 100644 index 0000000..7d5b7a9 --- /dev/null +++ b/examples/as-median/.gitignore @@ -0,0 +1,2 @@ +/build +/node_modules diff --git a/examples/as-median/Makefile b/examples/as-median/Makefile new file mode 100644 index 0000000..70cfe82 --- /dev/null +++ b/examples/as-median/Makefile @@ -0,0 +1,10 @@ + +.PHONY: build clean + +build: + npm run asbuild + +clean: + rm -f build/*.wasm + rm -f build/*.wasm.map + rm -f build/*.wat diff --git a/examples/as-median/asconfig.json b/examples/as-median/asconfig.json new file mode 100644 index 0000000..1627aaa --- /dev/null +++ b/examples/as-median/asconfig.json @@ -0,0 +1,20 @@ +{ + "targets": { + "debug": { + "binaryFile": "build/untouched.wasm", + "textFile": "build/untouched.wat", + "sourceMap": true, + "debug": true + }, + "release": { + "binaryFile": "build/optimized.wasm", + "textFile": "build/optimized.wat", + "sourceMap": true, + "optimizeLevel": 3, + "shrinkLevel": 0, + "converge": false, + "noAssert": false + } + }, + "options": {} +} \ No newline at end of file diff --git a/examples/as-median/assembly/index.ts b/examples/as-median/assembly/index.ts new file mode 100644 index 0000000..ed1f168 --- /dev/null +++ b/examples/as-median/assembly/index.ts @@ -0,0 +1,86 @@ + +import { JSONEncoder } from "assemblyscript-json" +import { parse, Arr, Integer, Value } from "assemblyscript-json/JSON"; + +export function exec(msg: usize, msg_size: usize, out_ptr: usize, out_size: usize): i32 { + + /* load input buffer into array */ + let in_buf = new Uint8Array(msg_size as i32); + for(let i: usize = 0; i < msg_size; i++) { + let byte = load(msg + i); + in_buf[i as i32] = byte; + } + + /* parse input buffer into an Array */ + let arr = parse(in_buf) as Arr; + let value_array = arr.valueOf() as Array; + let len = value_array.length; + let sample = new Array(len); + for(let i = 0; i < len; i++) { + let entry = value_array[i] as Integer; + sample[i] = entry.valueOf() as i32; + } + + let median = calc_median(len, sample); + + /* encode JSON object */ + let encoder = new JSONEncoder(); + encoder.pushObject(null); + encoder.setFloat("median", median); + encoder.popObject(); + + /* get pointer to buffer address */ + let out_buf = encoder.serialize().buffer; + let out_buf_len = out_buf.byteLength; + let out_buf_ptr = memory.data(8); + store(out_buf_ptr, out_buf); + store(out_ptr, out_buf_ptr); + + /* get pointer to buffer's size address */ + let out_size_ptr = memory.data(32); + store(out_size_ptr, out_buf_len); + store(out_size, out_size_ptr); + + return 0 +} + +/* recall that a median can have a fractional part */ +function calc_median(len: usize, val: Array): f64 { + val.sort(); + + /* + * In the following, `lmid` and `rmid` are the same whenever `val` has + * odd length. Note also that the average of 2 identical values is + * simply the value itself. + */ + let lmid = calc_mid(len, 0) as i32; + let rmid = calc_mid(len, 1) as i32; + + + /* calculate aforementioned average by leveraging distributivity */ + let lhalf = (val[lmid] as f64) / 2.0; + let rhalf = (val[rmid] as f64) / 2.0; + let median = lhalf + rhalf; + + return median +} + +function calc_mid(len: usize, rhs: bool): usize { + /* + * Compute the index of the order statistic corresponding to the median + * if the former exists. Otherwise, return a choice of one of the two + * closest order statistics. + */ + if (len % 2 == 0) { + if (rhs) { + let rmid = len / 2 + 1; + return rmid; + } else { + let lmid = len / 2; + return lmid; + } + } else { + let mid = (len + 1) / 2; + return mid; + } +} diff --git a/examples/as-median/assembly/tsconfig.json b/examples/as-median/assembly/tsconfig.json new file mode 100644 index 0000000..e28fcf2 --- /dev/null +++ b/examples/as-median/assembly/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "assemblyscript/std/assembly.json", + "include": [ + "./**/*.ts" + ] +} \ No newline at end of file diff --git a/examples/as-median/index.js b/examples/as-median/index.js new file mode 100644 index 0000000..06912f9 --- /dev/null +++ b/examples/as-median/index.js @@ -0,0 +1,5 @@ +const fs = require("fs"); +const loader = require("@assemblyscript/loader/umd"); +const imports = { /* imports go here */ }; +const wasmModule = loader.instantiateSync(fs.readFileSync(__dirname + "/build/optimized.wasm"), imports); +module.exports = wasmModule.exports; diff --git a/examples/as-median/package-lock.json b/examples/as-median/package-lock.json new file mode 100644 index 0000000..92cbb27 --- /dev/null +++ b/examples/as-median/package-lock.json @@ -0,0 +1,146 @@ +{ + "name": "as-median", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "as-median", + "version": "0.0.0", + "license": "Apache-2.0", + "dependencies": { + "@assemblyscript/loader": "^0.19.22", + "assemblyscript-json": "^1.1.0" + }, + "devDependencies": { + "assemblyscript": "^0.19.22" + } + }, + "node_modules/@assemblyscript/loader": { + "version": "0.19.23", + "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.19.23.tgz", + "integrity": "sha512-ulkCYfFbYj01ie1MDOyxv2F6SpRN1TOj7fQxbP07D6HmeR+gr2JLSmINKjga2emB+b1L2KGrFKBTc+e00p54nw==" + }, + "node_modules/assemblyscript": { + "version": "0.19.23", + "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.19.23.tgz", + "integrity": "sha512-fwOQNZVTMga5KRsfY80g7cpOl4PsFQczMwHzdtgoqLXaYhkhavufKb0sB0l3T1DUxpAufA0KNhlbpuuhZUwxMA==", + "dev": true, + "dependencies": { + "binaryen": "102.0.0-nightly.20211028", + "long": "^5.2.0", + "source-map-support": "^0.5.20" + }, + "bin": { + "asc": "bin/asc", + "asinit": "bin/asinit" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/assemblyscript" + } + }, + "node_modules/assemblyscript-json": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assemblyscript-json/-/assemblyscript-json-1.1.0.tgz", + "integrity": "sha512-UbE8ts8csTWQgd5TnSPN7MRV9NveuHv1bVnKmDLoo/tzjqxkmsZb3lu59Uk8H7SGoqdkDSEE049alx/nHnSdFw==" + }, + "node_modules/binaryen": { + "version": "102.0.0-nightly.20211028", + "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-102.0.0-nightly.20211028.tgz", + "integrity": "sha512-GCJBVB5exbxzzvyt8MGDv/MeUjs6gkXDvf4xOIItRBptYl0Tz5sm1o/uG95YK0L0VeG5ajDu3hRtkBP2kzqC5w==", + "dev": true, + "bin": { + "wasm-opt": "bin/wasm-opt" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/long": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.0.tgz", + "integrity": "sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + }, + "dependencies": { + "@assemblyscript/loader": { + "version": "0.19.23", + "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.19.23.tgz", + "integrity": "sha512-ulkCYfFbYj01ie1MDOyxv2F6SpRN1TOj7fQxbP07D6HmeR+gr2JLSmINKjga2emB+b1L2KGrFKBTc+e00p54nw==" + }, + "assemblyscript": { + "version": "0.19.23", + "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.19.23.tgz", + "integrity": "sha512-fwOQNZVTMga5KRsfY80g7cpOl4PsFQczMwHzdtgoqLXaYhkhavufKb0sB0l3T1DUxpAufA0KNhlbpuuhZUwxMA==", + "dev": true, + "requires": { + "binaryen": "102.0.0-nightly.20211028", + "long": "^5.2.0", + "source-map-support": "^0.5.20" + } + }, + "assemblyscript-json": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assemblyscript-json/-/assemblyscript-json-1.1.0.tgz", + "integrity": "sha512-UbE8ts8csTWQgd5TnSPN7MRV9NveuHv1bVnKmDLoo/tzjqxkmsZb3lu59Uk8H7SGoqdkDSEE049alx/nHnSdFw==" + }, + "binaryen": { + "version": "102.0.0-nightly.20211028", + "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-102.0.0-nightly.20211028.tgz", + "integrity": "sha512-GCJBVB5exbxzzvyt8MGDv/MeUjs6gkXDvf4xOIItRBptYl0Tz5sm1o/uG95YK0L0VeG5ajDu3hRtkBP2kzqC5w==", + "dev": true + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "long": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.0.tgz", + "integrity": "sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } +} diff --git a/examples/as-median/package.json b/examples/as-median/package.json new file mode 100644 index 0000000..c2c8452 --- /dev/null +++ b/examples/as-median/package.json @@ -0,0 +1,21 @@ +{ + "name": "as-median", + "version": "0.0.0", + "description": "Calculate median of a dataset", + "main": "index.js", + "scripts": { + "test": "node tests", + "asbuild:untouched": "asc assembly/index.ts --target debug", + "asbuild:optimized": "asc assembly/index.ts --target release", + "asbuild": "npm run asbuild:untouched && npm run asbuild:optimized" + }, + "author": "ntls.io", + "license": "Apache-2.0", + "dependencies": { + "@assemblyscript/loader": "^0.19.22", + "assemblyscript-json": "^1.1.0" + }, + "devDependencies": { + "assemblyscript": "^0.19.22" + } +}