commit e811c04eebb8240c77f243e9617f8a6e9a19701e Author: kura Date: Fri Dec 13 15:20:28 2024 +0800 init diff --git a/convex_hull.c b/convex_hull.c new file mode 100644 index 0000000..1253ae3 --- /dev/null +++ b/convex_hull.c @@ -0,0 +1,42 @@ +#include + +// 定义一个点结构体 +typedef struct { + int x, y; +} Point; + +// 计算两点的极角 +int orientation(Point p, Point q, Point r) { + int val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); + if (val == 0) return 0; // 共线 + return (val > 0) ? 1 : 2; // 顺时针或逆时针 +} + +// 对点的极角排序 +int compare(const void *vp1, const void *vp2) { + Point *p1 = (Point *)vp1; + Point *p2 = (Point *)vp2; + return (p1->y < p2->y) || (p1->y == p2->y && p1->x < p2->x); +} + +// 凸包主函数 +void convexHull(Point points[], int n, Point result[], int *result_size) { + // 如果点数小于 3,无法构成凸包 + if (n < 3) { + *result_size = 0; + return; + } + + // 按 y 坐标排序,如果 y 坐标相同则按 x 坐标排序 + qsort(points, n, sizeof(Point), compare); + + // 构建凸包 + int m = 0; // 凸包的点数 + for (int i = 0; i < n; i++) { + while (m >= 2 && orientation(result[m-2], result[m-1], points[i]) != 2) + m--; + result[m++] = points[i]; + } + + *result_size = m; +} \ No newline at end of file diff --git a/convex_hull.js b/convex_hull.js new file mode 100644 index 0000000..117d28b --- /dev/null +++ b/convex_hull.js @@ -0,0 +1,2614 @@ +// include: shell.js +// The Module object: Our interface to the outside world. We import +// and export values on it. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(Module) { ..generated code.. } +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to check if Module already exists (e.g. case 3 above). +// Substitution will be replaced with actual code on later stage of the build, +// this way Closure Compiler will not mangle it (e.g. case 4. above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module = typeof Module != 'undefined' ? Module : {}; + +// --pre-jses are emitted after the Module integration code, so that they can +// refer to Module (if they choose; they can also define Module) + + +// Sometimes an existing Module object exists with properties +// meant to overwrite the default module functionality. Here +// we collect those properties and reapply _after_ we configure +// the current environment's defaults to avoid having to be so +// defensive during initialization. +var moduleOverrides = Object.assign({}, Module); + +var arguments_ = []; +var thisProgram = './this.program'; +var quit_ = (status, toThrow) => { + throw toThrow; +}; + +// Determine the runtime environment we are in. You can customize this by +// setting the ENVIRONMENT setting at compile time (see settings.js). + +// Attempt to auto-detect the environment +var ENVIRONMENT_IS_WEB = typeof window == 'object'; +var ENVIRONMENT_IS_WORKER = typeof importScripts == 'function'; +// N.b. Electron.js environment is simultaneously a NODE-environment, but +// also a web environment. +var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + +if (Module['ENVIRONMENT']) { + throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)'); +} + +// Three configurations we can be running in: +// 1) We could be the application main() thread running in the main JS UI thread. (ENVIRONMENT_IS_WORKER == false and ENVIRONMENT_IS_PTHREAD == false) +// 2) We could be the application main() thread proxied to worker. (with Emscripten -sPROXY_TO_WORKER) (ENVIRONMENT_IS_WORKER == true, ENVIRONMENT_IS_PTHREAD == false) +// 3) We could be an application pthread running in a worker. (ENVIRONMENT_IS_WORKER == true and ENVIRONMENT_IS_PTHREAD == true) + +// ENVIRONMENT_IS_PTHREAD=true will have been preset in worker.js. Make it false in the main runtime thread. +var ENVIRONMENT_IS_PTHREAD = Module['ENVIRONMENT_IS_PTHREAD'] || false; + +// In MODULARIZE mode _scriptDir needs to be captured already at the very top of the page immediately when the page is parsed, so it is generated there +// before the page load. In non-MODULARIZE modes generate it here. +var _scriptDir = (typeof document != 'undefined' && document.currentScript) ? document.currentScript.src : undefined; + +if (ENVIRONMENT_IS_WORKER) { + _scriptDir = self.location.href; +} +else if (ENVIRONMENT_IS_NODE) { + _scriptDir = __filename; +} + +// `/` should be present at the end if `scriptDirectory` is not empty +var scriptDirectory = ''; +function locateFile(path) { + if (Module['locateFile']) { + return Module['locateFile'](path, scriptDirectory); + } + return scriptDirectory + path; +} + +// Hooks that are implemented differently in different runtime environments. +var read_, + readAsync, + readBinary; + +if (ENVIRONMENT_IS_NODE) { + if (typeof process == 'undefined' || !process.release || process.release.name !== 'node') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + var nodeVersion = process.versions.node; + var numericVersion = nodeVersion.split('.').slice(0, 3); + numericVersion = (numericVersion[0] * 10000) + (numericVersion[1] * 100) + (numericVersion[2].split('-')[0] * 1); + var minVersion = 160000; + if (numericVersion < 160000) { + throw new Error('This emscripten-generated code requires node v16.0.0 (detected v' + nodeVersion + ')'); + } + + // `require()` is no-op in an ESM module, use `createRequire()` to construct + // the require()` function. This is only necessary for multi-environment + // builds, `-sENVIRONMENT=node` emits a static import declaration instead. + // TODO: Swap all `require()`'s with `import()`'s? + // These modules will usually be used on Node.js. Load them eagerly to avoid + // the complexity of lazy-loading. + var fs = require('fs'); + var nodePath = require('path'); + + if (ENVIRONMENT_IS_WORKER) { + scriptDirectory = nodePath.dirname(scriptDirectory) + '/'; + } else { + scriptDirectory = __dirname + '/'; + } + +// include: node_shell_read.js +read_ = (filename, binary) => { + // We need to re-wrap `file://` strings to URLs. Normalizing isn't + // necessary in that case, the path should already be absolute. + filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); + return fs.readFileSync(filename, binary ? undefined : 'utf8'); +}; + +readBinary = (filename) => { + var ret = read_(filename, true); + if (!ret.buffer) { + ret = new Uint8Array(ret); + } + assert(ret.buffer); + return ret; +}; + +readAsync = (filename, onload, onerror, binary = true) => { + // See the comment in the `read_` function. + filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); + fs.readFile(filename, binary ? undefined : 'utf8', (err, data) => { + if (err) onerror(err); + else onload(binary ? data.buffer : data); + }); +}; +// end include: node_shell_read.js + if (!Module['thisProgram'] && process.argv.length > 1) { + thisProgram = process.argv[1].replace(/\\/g, '/'); + } + + arguments_ = process.argv.slice(2); + + if (typeof module != 'undefined') { + module['exports'] = Module; + } + + process.on('uncaughtException', (ex) => { + // suppress ExitStatus exceptions from showing an error + if (ex !== 'unwind' && !(ex instanceof ExitStatus) && !(ex.context instanceof ExitStatus)) { + throw ex; + } + }); + + quit_ = (status, toThrow) => { + process.exitCode = status; + throw toThrow; + }; + + global.Worker = require('worker_threads').Worker; + +} else +if (ENVIRONMENT_IS_SHELL) { + + if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof importScripts == 'function') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + if (typeof read != 'undefined') { + read_ = read; + } + + readBinary = (f) => { + if (typeof readbuffer == 'function') { + return new Uint8Array(readbuffer(f)); + } + let data = read(f, 'binary'); + assert(typeof data == 'object'); + return data; + }; + + readAsync = (f, onload, onerror) => { + setTimeout(() => onload(readBinary(f))); + }; + + if (typeof clearTimeout == 'undefined') { + globalThis.clearTimeout = (id) => {}; + } + + if (typeof setTimeout == 'undefined') { + // spidermonkey lacks setTimeout but we use it above in readAsync. + globalThis.setTimeout = (f) => (typeof f == 'function') ? f() : abort(); + } + + if (typeof scriptArgs != 'undefined') { + arguments_ = scriptArgs; + } else if (typeof arguments != 'undefined') { + arguments_ = arguments; + } + + if (typeof quit == 'function') { + quit_ = (status, toThrow) => { + // Unlike node which has process.exitCode, d8 has no such mechanism. So we + // have no way to set the exit code and then let the program exit with + // that code when it naturally stops running (say, when all setTimeouts + // have completed). For that reason, we must call `quit` - the only way to + // set the exit code - but quit also halts immediately. To increase + // consistency with node (and the web) we schedule the actual quit call + // using a setTimeout to give the current stack and any exception handlers + // a chance to run. This enables features such as addOnPostRun (which + // expected to be able to run code after main returns). + setTimeout(() => { + if (!(toThrow instanceof ExitStatus)) { + let toLog = toThrow; + if (toThrow && typeof toThrow == 'object' && toThrow.stack) { + toLog = [toThrow, toThrow.stack]; + } + err(`exiting due to exception: ${toLog}`); + } + quit(status); + }); + throw toThrow; + }; + } + + if (typeof print != 'undefined') { + // Prefer to use print/printErr where they exist, as they usually work better. + if (typeof console == 'undefined') console = /** @type{!Console} */({}); + console.log = /** @type{!function(this:Console, ...*): undefined} */ (print); + console.warn = console.error = /** @type{!function(this:Console, ...*): undefined} */ (typeof printErr != 'undefined' ? printErr : print); + } + +} else + +// Note that this includes Node.js workers when relevant (pthreads is enabled). +// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and +// ENVIRONMENT_IS_NODE. +if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled + scriptDirectory = self.location.href; + } else if (typeof document != 'undefined' && document.currentScript) { // web + scriptDirectory = document.currentScript.src; + } + // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. + // otherwise, slice off the final part of the url to find the script directory. + // if scriptDirectory does not contain a slash, lastIndexOf will return -1, + // and scriptDirectory will correctly be replaced with an empty string. + // If scriptDirectory contains a query (starting with ?) or a fragment (starting with #), + // they are removed because they could contain a slash. + if (scriptDirectory.startsWith('blob:')) { + scriptDirectory = ''; + } else { + scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, '').lastIndexOf('/')+1); + } + + if (!(typeof window == 'object' || typeof importScripts == 'function')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + // Differentiate the Web Worker from the Node Worker case, as reading must + // be done differently. + if (!ENVIRONMENT_IS_NODE) + { +// include: web_or_worker_shell_read.js +read_ = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + } + + if (ENVIRONMENT_IS_WORKER) { + readBinary = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.responseType = 'arraybuffer'; + xhr.send(null); + return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response)); + }; + } + + readAsync = (url, onload, onerror) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = () => { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + return; + } + onerror(); + }; + xhr.onerror = onerror; + xhr.send(null); + } + +// end include: web_or_worker_shell_read.js + } +} else +{ + throw new Error('environment detection error'); +} + +if (ENVIRONMENT_IS_NODE) { + // Polyfill the performance object, which emscripten pthreads support + // depends on for good timing. + if (typeof performance == 'undefined') { + global.performance = require('perf_hooks').performance; + } +} + +// Set up the out() and err() hooks, which are how we can print to stdout or +// stderr, respectively. +// Normally just binding console.log/console.error here works fine, but +// under node (with workers) we see missing/out-of-order messages so route +// directly to stdout and stderr. +// See https://github.com/emscripten-core/emscripten/issues/14804 +var defaultPrint = console.log.bind(console); +var defaultPrintErr = console.error.bind(console); +if (ENVIRONMENT_IS_NODE) { + defaultPrint = (...args) => fs.writeSync(1, args.join(' ') + '\n'); + defaultPrintErr = (...args) => fs.writeSync(2, args.join(' ') + '\n'); +} +var out = Module['print'] || defaultPrint; +var err = Module['printErr'] || defaultPrintErr; + +// Merge back in the overrides +Object.assign(Module, moduleOverrides); +// Free the object hierarchy contained in the overrides, this lets the GC +// reclaim data used. +moduleOverrides = null; +checkIncomingModuleAPI(); + +// Emit code to handle expected values on the Module object. This applies Module.x +// to the proper local x. This has two benefits: first, we only emit it if it is +// expected to arrive, and second, by using a local everywhere else that can be +// minified. + +if (Module['arguments']) arguments_ = Module['arguments'];legacyModuleProp('arguments', 'arguments_'); + +if (Module['thisProgram']) thisProgram = Module['thisProgram'];legacyModuleProp('thisProgram', 'thisProgram'); + +if (Module['quit']) quit_ = Module['quit'];legacyModuleProp('quit', 'quit_'); + +// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message +// Assertions on removed incoming Module JS APIs. +assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['read'] == 'undefined', 'Module.read option was removed (modify read_ in JS)'); +assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)'); +assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)'); +assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)'); +assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY'); +legacyModuleProp('asm', 'wasmExports'); +legacyModuleProp('read', 'read_'); +legacyModuleProp('readAsync', 'readAsync'); +legacyModuleProp('readBinary', 'readBinary'); +legacyModuleProp('setWindowTitle', 'setWindowTitle'); +var IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js'; +var PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js'; +var WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js'; +var FETCHFS = 'FETCHFS is no longer included by default; build with -lfetchfs.js'; +var ICASEFS = 'ICASEFS is no longer included by default; build with -licasefs.js'; +var JSFILEFS = 'JSFILEFS is no longer included by default; build with -ljsfilefs.js'; +var OPFS = 'OPFS is no longer included by default; build with -lopfs.js'; + +var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js'; + +assert( + ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER || ENVIRONMENT_IS_NODE, 'Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)'); + +assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.'); + +// end include: shell.js + +// include: preamble.js +// === Preamble library stuff === + +// Documentation for the public APIs defined in this file must be updated in: +// site/source/docs/api_reference/preamble.js.rst +// A prebuilt local version of the documentation is available at: +// site/build/text/docs/api_reference/preamble.js.txt +// You can also build docs locally as HTML or other formats in site/ +// An online HTML version (which may be of a different version of Emscripten) +// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html + +var wasmBinary; +if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary'); + +if (typeof WebAssembly != 'object') { + err('no native wasm support detected'); +} + +// Wasm globals + +var wasmMemory; + +// For sending to workers. +var wasmModule; + +//======================================== +// Runtime essentials +//======================================== + +// whether we are quitting the application. no code should run after this. +// set in exit() and abort() +var ABORT = false; + +// set by exit() and abort(). Passed to 'onExit' handler. +// NOTE: This is also used as the process return code code in shell environments +// but only when noExitRuntime is false. +var EXITSTATUS; + +// In STRICT mode, we only define assert() when ASSERTIONS is set. i.e. we +// don't define it at all in release modes. This matches the behaviour of +// MINIMAL_RUNTIME. +// TODO(sbc): Make this the default even without STRICT enabled. +/** @type {function(*, string=)} */ +function assert(condition, text) { + if (!condition) { + abort('Assertion failed' + (text ? ': ' + text : '')); + } +} + +// We used to include malloc/free by default in the past. Show a helpful error in +// builds with assertions. + +// Memory management + +var HEAP, +/** @type {!Int8Array} */ + HEAP8, +/** @type {!Uint8Array} */ + HEAPU8, +/** @type {!Int16Array} */ + HEAP16, +/** @type {!Uint16Array} */ + HEAPU16, +/** @type {!Int32Array} */ + HEAP32, +/** @type {!Uint32Array} */ + HEAPU32, +/** @type {!Float32Array} */ + HEAPF32, +/** @type {!Float64Array} */ + HEAPF64; + +// include: runtime_shared.js +function updateMemoryViews() { + var b = wasmMemory.buffer; + Module['HEAP8'] = HEAP8 = new Int8Array(b); + Module['HEAP16'] = HEAP16 = new Int16Array(b); + Module['HEAPU8'] = HEAPU8 = new Uint8Array(b); + Module['HEAPU16'] = HEAPU16 = new Uint16Array(b); + Module['HEAP32'] = HEAP32 = new Int32Array(b); + Module['HEAPU32'] = HEAPU32 = new Uint32Array(b); + Module['HEAPF32'] = HEAPF32 = new Float32Array(b); + Module['HEAPF64'] = HEAPF64 = new Float64Array(b); +} +// end include: runtime_shared.js +assert(!Module['STACK_SIZE'], 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time') + +assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined, + 'JS engine does not provide full typed array support'); + +// In non-standalone/normal mode, we create the memory here. +// include: runtime_init_memory.js +// Create the wasm memory. (Note: this only applies if IMPORTED_MEMORY is defined) + +var INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 16777216;legacyModuleProp('INITIAL_MEMORY', 'INITIAL_MEMORY'); + +assert(INITIAL_MEMORY >= 65536, 'INITIAL_MEMORY should be larger than STACK_SIZE, was ' + INITIAL_MEMORY + '! (STACK_SIZE=' + 65536 + ')'); + +// check for full engine support (use string 'subarray' to avoid closure compiler confusion) + +if (ENVIRONMENT_IS_PTHREAD) { + wasmMemory = Module['wasmMemory']; +} else { + + if (Module['wasmMemory']) { + wasmMemory = Module['wasmMemory']; + } else + { + wasmMemory = new WebAssembly.Memory({ + 'initial': INITIAL_MEMORY / 65536, + 'maximum': INITIAL_MEMORY / 65536, + 'shared': true, + }); + if (!(wasmMemory.buffer instanceof SharedArrayBuffer)) { + err('requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag'); + if (ENVIRONMENT_IS_NODE) { + err('(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and/or recent version)'); + } + throw Error('bad memory'); + } + } + +} + +updateMemoryViews(); + +// If the user provides an incorrect length, just use that length instead rather than providing the user to +// specifically provide the memory length with Module['INITIAL_MEMORY']. +INITIAL_MEMORY = wasmMemory.buffer.byteLength; +assert(INITIAL_MEMORY % 65536 === 0); +// end include: runtime_init_memory.js + +// include: runtime_stack_check.js +// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode. +function writeStackCookie() { + var max = _emscripten_stack_get_end(); + assert((max & 3) == 0); + // If the stack ends at address zero we write our cookies 4 bytes into the + // stack. This prevents interference with SAFE_HEAP and ASAN which also + // monitor writes to address zero. + if (max == 0) { + max += 4; + } + // The stack grow downwards towards _emscripten_stack_get_end. + // We write cookies to the final two words in the stack and detect if they are + // ever overwritten. + HEAPU32[((max)>>2)] = 0x02135467; + HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE; + // Also test the global address 0 for integrity. + HEAPU32[((0)>>2)] = 1668509029; +} + +function checkStackCookie() { + if (ABORT) return; + var max = _emscripten_stack_get_end(); + // See writeStackCookie(). + if (max == 0) { + max += 4; + } + var cookie1 = HEAPU32[((max)>>2)]; + var cookie2 = HEAPU32[(((max)+(4))>>2)]; + if (cookie1 != 0x02135467 || cookie2 != 0x89BACDFE) { + abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`); + } + // Also test the global address 0 for integrity. + if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) { + abort('Runtime error: The application has corrupted its heap memory area (address zero)!'); + } +} +// end include: runtime_stack_check.js +// include: runtime_assertions.js +// Endianness check +(function() { + var h16 = new Int16Array(1); + var h8 = new Int8Array(h16.buffer); + h16[0] = 0x6373; + if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)'; +})(); + +// end include: runtime_assertions.js +var __ATPRERUN__ = []; // functions called before the runtime is initialized +var __ATINIT__ = []; // functions called during startup +var __ATEXIT__ = []; // functions called during shutdown +var __ATPOSTRUN__ = []; // functions called after the main() is called + +var runtimeInitialized = false; + +function preRun() { + assert(!ENVIRONMENT_IS_PTHREAD); // PThreads reuse the runtime from the main thread. + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } + } + callRuntimeCallbacks(__ATPRERUN__); +} + +function initRuntime() { + assert(!runtimeInitialized); + runtimeInitialized = true; + + if (ENVIRONMENT_IS_PTHREAD) return; + + checkStackCookie(); + + + callRuntimeCallbacks(__ATINIT__); +} + +function postRun() { + checkStackCookie(); + if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread. + + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } + } + + callRuntimeCallbacks(__ATPOSTRUN__); +} + +function addOnPreRun(cb) { + __ATPRERUN__.unshift(cb); +} + +function addOnInit(cb) { + __ATINIT__.unshift(cb); +} + +function addOnExit(cb) { +} + +function addOnPostRun(cb) { + __ATPOSTRUN__.unshift(cb); +} + +// include: runtime_math.js +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc + +assert(Math.imul, 'This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.fround, 'This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.clz32, 'This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +// end include: runtime_math.js +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// Module.preRun (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyWatcher = null; +var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled +var runDependencyTracking = {}; + +function getUniqueRunDependency(id) { + var orig = id; + while (1) { + if (!runDependencyTracking[id]) return id; + id = orig + Math.random(); + } +} + +function addRunDependency(id) { + runDependencies++; + + Module['monitorRunDependencies']?.(runDependencies); + + if (id) { + assert(!runDependencyTracking[id]); + runDependencyTracking[id] = 1; + if (runDependencyWatcher === null && typeof setInterval != 'undefined') { + // Check for missing dependencies every few seconds + runDependencyWatcher = setInterval(() => { + if (ABORT) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + return; + } + var shown = false; + for (var dep in runDependencyTracking) { + if (!shown) { + shown = true; + err('still waiting on run dependencies:'); + } + err(`dependency: ${dep}`); + } + if (shown) { + err('(end of list)'); + } + }, 10000); + } + } else { + err('warning: run dependency added without ID'); + } +} + +function removeRunDependency(id) { + runDependencies--; + + Module['monitorRunDependencies']?.(runDependencies); + + if (id) { + assert(runDependencyTracking[id]); + delete runDependencyTracking[id]; + } else { + err('warning: run dependency removed without ID'); + } + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } +} + +/** @param {string|number=} what */ +function abort(what) { + Module['onAbort']?.(what); + + what = 'Aborted(' + what + ')'; + // TODO(sbc): Should we remove printing and leave it up to whoever + // catches the exception? + err(what); + + ABORT = true; + EXITSTATUS = 1; + + // Use a wasm runtime error, because a JS error might be seen as a foreign + // exception, which means we'd run destructors on it. We need the error to + // simply make the program stop. + // FIXME This approach does not work in Wasm EH because it currently does not assume + // all RuntimeErrors are from traps; it decides whether a RuntimeError is from + // a trap or not based on a hidden field within the object. So at the moment + // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that + // allows this in the wasm spec. + + // Suppress closure compiler warning here. Closure compiler's builtin extern + // definition for WebAssembly.RuntimeError claims it takes no arguments even + // though it can. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed. + /** @suppress {checkTypes} */ + var e = new WebAssembly.RuntimeError(what); + + // Throw the error whether or not MODULARIZE is set because abort is used + // in code paths apart from instantiation where an exception is expected + // to be thrown when abort is called. + throw e; +} + +// include: memoryprofiler.js +// end include: memoryprofiler.js +// show errors on likely calls to FS when it was not included +var FS = { + error() { + abort('Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -sFORCE_FILESYSTEM'); + }, + init() { FS.error() }, + createDataFile() { FS.error() }, + createPreloadedFile() { FS.error() }, + createLazyFile() { FS.error() }, + open() { FS.error() }, + mkdev() { FS.error() }, + registerDevice() { FS.error() }, + analyzePath() { FS.error() }, + + ErrnoError() { FS.error() }, +}; +Module['FS_createDataFile'] = FS.createDataFile; +Module['FS_createPreloadedFile'] = FS.createPreloadedFile; + +// include: URIUtils.js +// Prefix of data URIs emitted by SINGLE_FILE and related options. +var dataURIPrefix = 'data:application/octet-stream;base64,'; + +/** + * Indicates whether filename is a base64 data URI. + * @noinline + */ +var isDataURI = (filename) => filename.startsWith(dataURIPrefix); + +/** + * Indicates whether filename is delivered via file protocol (as opposed to http/https) + * @noinline + */ +var isFileURI = (filename) => filename.startsWith('file://'); +// end include: URIUtils.js +function createExportWrapper(name) { + return (...args) => { + assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`); + var f = wasmExports[name]; + assert(f, `exported native function \`${name}\` not found`); + return f(...args); + }; +} + +// include: runtime_exceptions.js +// end include: runtime_exceptions.js +var wasmBinaryFile; + wasmBinaryFile = 'convex_hull.wasm'; + if (!isDataURI(wasmBinaryFile)) { + wasmBinaryFile = locateFile(wasmBinaryFile); + } + +function getBinarySync(file) { + if (file == wasmBinaryFile && wasmBinary) { + return new Uint8Array(wasmBinary); + } + if (readBinary) { + return readBinary(file); + } + throw 'both async and sync fetching of the wasm failed'; +} + +function getBinaryPromise(binaryFile) { + // If we don't have the binary yet, try to load it asynchronously. + // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url. + // See https://github.com/github/fetch/pull/92#issuecomment-140665932 + // Cordova or Electron apps are typically loaded from a file:// url. + // So use fetch if it is available and the url is not a file, otherwise fall back to XHR. + if (!wasmBinary + && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { + if (typeof fetch == 'function' + && !isFileURI(binaryFile) + ) { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + if (!response['ok']) { + throw `failed to load wasm binary file at '${binaryFile}'`; + } + return response['arrayBuffer'](); + }).catch(() => getBinarySync(binaryFile)); + } + else if (readAsync) { + // fetch is not available or url is file => try XHR (readAsync uses XHR internally) + return new Promise((resolve, reject) => { + readAsync(binaryFile, (response) => resolve(new Uint8Array(/** @type{!ArrayBuffer} */(response))), reject) + }); + } + } + + // Otherwise, getBinarySync should be able to get it synchronously + return Promise.resolve().then(() => getBinarySync(binaryFile)); +} + +function instantiateArrayBuffer(binaryFile, imports, receiver) { + return getBinaryPromise(binaryFile).then((binary) => { + return WebAssembly.instantiate(binary, imports); + }).then(receiver, (reason) => { + err(`failed to asynchronously prepare wasm: ${reason}`); + + // Warn on some common problems. + if (isFileURI(wasmBinaryFile)) { + err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`); + } + abort(reason); + }); +} + +function instantiateAsync(binary, binaryFile, imports, callback) { + if (!binary && + typeof WebAssembly.instantiateStreaming == 'function' && + !isDataURI(binaryFile) && + // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously. + !isFileURI(binaryFile) && + // Avoid instantiateStreaming() on Node.js environment for now, as while + // Node.js v18.1.0 implements it, it does not have a full fetch() + // implementation yet. + // + // Reference: + // https://github.com/emscripten-core/emscripten/pull/16917 + !ENVIRONMENT_IS_NODE && + typeof fetch == 'function') { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + // Suppress closure warning here since the upstream definition for + // instantiateStreaming only allows Promise rather than + // an actual Response. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed. + /** @suppress {checkTypes} */ + var result = WebAssembly.instantiateStreaming(response, imports); + + return result.then( + callback, + function(reason) { + // We expect the most common failure cause to be a bad MIME type for the binary, + // in which case falling back to ArrayBuffer instantiation should work. + err(`wasm streaming compile failed: ${reason}`); + err('falling back to ArrayBuffer instantiation'); + return instantiateArrayBuffer(binaryFile, imports, callback); + }); + }); + } + return instantiateArrayBuffer(binaryFile, imports, callback); +} + +// Create the wasm instance. +// Receives the wasm imports, returns the exports. +function createWasm() { + // prepare imports + var info = { + 'env': wasmImports, + 'wasi_snapshot_preview1': wasmImports, + }; + // Load the wasm module and create an instance of using native support in the JS engine. + // handle a generated wasm instance, receiving its exports and + // performing other necessary setup + /** @param {WebAssembly.Module=} module*/ + function receiveInstance(instance, module) { + wasmExports = instance.exports; + + + + registerTLSInit(wasmExports['_emscripten_tls_init']); + + wasmTable = wasmExports['__indirect_function_table']; + + assert(wasmTable, 'table not found in wasm exports'); + + addOnInit(wasmExports['__wasm_call_ctors']); + + // We now have the Wasm module loaded up, keep a reference to the compiled module so we can post it to the workers. + wasmModule = module; + removeRunDependency('wasm-instantiate'); + return wasmExports; + } + // wait for the pthread pool (if any) + addRunDependency('wasm-instantiate'); + + // Prefer streaming instantiation if available. + // Async compilation can be confusing when an error on the page overwrites Module + // (for example, if the order of elements is wrong, and the one defining Module is + // later), so we save Module and check it later. + var trueModule = Module; + function receiveInstantiationResult(result) { + // 'result' is a ResultObject object which has both the module and instance. + // receiveInstance() will swap in the exports (to Module.asm) so they can be called + assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?'); + trueModule = null; + receiveInstance(result['instance'], result['module']); + } + + // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback + // to manually instantiate the Wasm module themselves. This allows pages to + // run the instantiation parallel to any other async startup actions they are + // performing. + // Also pthreads and wasm workers initialize the wasm instance through this + // path. + if (Module['instantiateWasm']) { + + try { + return Module['instantiateWasm'](info, receiveInstance); + } catch(e) { + err(`Module.instantiateWasm callback failed with error: ${e}`); + return false; + } + } + + instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult); + return {}; // no exports yet; we'll fill them in later +} + +// Globals used by JS i64 conversions (see makeSetValue) +var tempDouble; +var tempI64; + +// include: runtime_debug.js +function legacyModuleProp(prop, newName, incoming=true) { + if (!Object.getOwnPropertyDescriptor(Module, prop)) { + Object.defineProperty(Module, prop, { + configurable: true, + get() { + let extra = incoming ? ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)' : ''; + abort(`\`Module.${prop}\` has been replaced by \`${newName}\`` + extra); + + } + }); + } +} + +function ignoredModuleProp(prop) { + if (Object.getOwnPropertyDescriptor(Module, prop)) { + abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`); + } +} + +// forcing the filesystem exports a few things by default +function isExportedByForceFilesystem(name) { + return name === 'FS_createPath' || + name === 'FS_createDataFile' || + name === 'FS_createPreloadedFile' || + name === 'FS_unlink' || + name === 'addRunDependency' || + // The old FS has some functionality that WasmFS lacks. + name === 'FS_createLazyFile' || + name === 'FS_createDevice' || + name === 'removeRunDependency'; +} + +function missingGlobal(sym, msg) { + if (typeof globalThis !== 'undefined') { + Object.defineProperty(globalThis, sym, { + configurable: true, + get() { + warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`); + return undefined; + } + }); + } +} + +missingGlobal('buffer', 'Please use HEAP8.buffer or wasmMemory.buffer'); +missingGlobal('asm', 'Please use wasmExports instead'); + +function missingLibrarySymbol(sym) { + if (typeof globalThis !== 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) { + Object.defineProperty(globalThis, sym, { + configurable: true, + get() { + // Can't `abort()` here because it would break code that does runtime + // checks. e.g. `if (typeof SDL === 'undefined')`. + var msg = `\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`; + // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in + // library.js, which means $name for a JS name with no prefix, or name + // for a JS name like _name. + var librarySymbol = sym; + if (!librarySymbol.startsWith('_')) { + librarySymbol = '$' + sym; + } + msg += ` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + warnOnce(msg); + return undefined; + } + }); + } + // Any symbol that is not included from the JS library is also (by definition) + // not exported on the Module object. + unexportedRuntimeSymbol(sym); +} + +function unexportedRuntimeSymbol(sym) { + if (!Object.getOwnPropertyDescriptor(Module, sym)) { + Object.defineProperty(Module, sym, { + configurable: true, + get() { + var msg = `'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + abort(msg); + } + }); + } +} + +// Used by XXXXX_DEBUG settings to output debug messages. +function dbg(...args) { + // Avoid using the console for debugging in multi-threaded node applications + // See https://github.com/emscripten-core/emscripten/issues/14804 + if (ENVIRONMENT_IS_NODE) { + fs.writeSync(2, args.join(' ') + '\n'); + } else + // TODO(sbc): Make this configurable somehow. Its not always convenient for + // logging to show up as warnings. + console.warn(...args); +} +// end include: runtime_debug.js +// === Body === +// end include: preamble.js + + + /** @constructor */ + function ExitStatus(status) { + this.name = 'ExitStatus'; + this.message = `Program terminated with exit(${status})`; + this.status = status; + } + + + + var terminateWorker = (worker) => { + worker.terminate(); + // terminate() can be asynchronous, so in theory the worker can continue + // to run for some amount of time after termination. However from our POV + // the worker now dead and we don't want to hear from it again, so we stub + // out its message handler here. This avoids having to check in each of + // the onmessage handlers if the message was coming from valid worker. + worker.onmessage = (e) => { + var cmd = e['data']['cmd']; + err(`received "${cmd}" command from terminated worker: ${worker.workerID}`); + }; + }; + + var killThread = (pthread_ptr) => { + assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! killThread() can only ever be called from main application thread!'); + assert(pthread_ptr, 'Internal Error! Null pthread_ptr in killThread!'); + var worker = PThread.pthreads[pthread_ptr]; + delete PThread.pthreads[pthread_ptr]; + terminateWorker(worker); + __emscripten_thread_free_data(pthread_ptr); + // The worker was completely nuked (not just the pthread execution it was hosting), so remove it from running workers + // but don't put it back to the pool. + PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker), 1); // Not a running Worker anymore. + worker.pthread_ptr = 0; + }; + + var cancelThread = (pthread_ptr) => { + assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! cancelThread() can only ever be called from main application thread!'); + assert(pthread_ptr, 'Internal Error! Null pthread_ptr in cancelThread!'); + var worker = PThread.pthreads[pthread_ptr]; + worker.postMessage({ 'cmd': 'cancel' }); + }; + + var cleanupThread = (pthread_ptr) => { + assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! cleanupThread() can only ever be called from main application thread!'); + assert(pthread_ptr, 'Internal Error! Null pthread_ptr in cleanupThread!'); + var worker = PThread.pthreads[pthread_ptr]; + assert(worker); + PThread.returnWorkerToPool(worker); + }; + + var zeroMemory = (address, size) => { + HEAPU8.fill(0, address, address + size); + return address; + }; + + var spawnThread = (threadParams) => { + assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! spawnThread() can only ever be called from main application thread!'); + assert(threadParams.pthread_ptr, 'Internal error, no pthread ptr!'); + + var worker = PThread.getNewWorker(); + if (!worker) { + // No available workers in the PThread pool. + return 6; + } + assert(!worker.pthread_ptr, 'Internal error!'); + + PThread.runningWorkers.push(worker); + + // Add to pthreads map + PThread.pthreads[threadParams.pthread_ptr] = worker; + + worker.pthread_ptr = threadParams.pthread_ptr; + var msg = { + 'cmd': 'run', + 'start_routine': threadParams.startRoutine, + 'arg': threadParams.arg, + 'pthread_ptr': threadParams.pthread_ptr, + }; + if (ENVIRONMENT_IS_NODE) { + // Mark worker as weakly referenced once we start executing a pthread, + // so that its existence does not prevent Node.js from exiting. This + // has no effect if the worker is already weakly referenced (e.g. if + // this worker was previously idle/unused). + worker.unref(); + } + // Ask the worker to start executing its pthread entry point function. + worker.postMessage(msg, threadParams.transferList); + return 0; + }; + + + + var runtimeKeepaliveCounter = 0; + var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0; + + + var withStackSave = (f) => { + var stack = stackSave(); + var ret = f(); + stackRestore(stack); + return ret; + }; + + + var convertI32PairToI53Checked = (lo, hi) => { + assert(lo == (lo >>> 0) || lo == (lo|0)); // lo should either be a i32 or a u32 + assert(hi === (hi|0)); // hi should be a i32 + return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN; + }; + + /** @type{function(number, (number|boolean), ...number)} */ + var proxyToMainThread = (funcIndex, emAsmAddr, sync, ...callArgs) => { + // EM_ASM proxying is done by passing a pointer to the address of the EM_ASM + // content as `emAsmAddr`. JS library proxying is done by passing an index + // into `proxiedJSCallArgs` as `funcIndex`. If `emAsmAddr` is non-zero then + // `funcIndex` will be ignored. + // Additional arguments are passed after the first three are the actual + // function arguments. + // The serialization buffer contains the number of call params, and then + // all the args here. + // We also pass 'sync' to C separately, since C needs to look at it. + // Allocate a buffer, which will be copied by the C code. + return withStackSave(() => { + // First passed parameter specifies the number of arguments to the function. + // When BigInt support is enabled, we must handle types in a more complex + // way, detecting at runtime if a value is a BigInt or not (as we have no + // type info here). To do that, add a "prefix" before each value that + // indicates if it is a BigInt, which effectively doubles the number of + // values we serialize for proxying. TODO: pack this? + var serializedNumCallArgs = callArgs.length ; + var args = stackAlloc(serializedNumCallArgs * 8); + var b = ((args)>>3); + for (var i = 0; i < callArgs.length; i++) { + var arg = callArgs[i]; + HEAPF64[b + i] = arg; + } + return __emscripten_run_on_main_thread_js(funcIndex, emAsmAddr, serializedNumCallArgs, args, sync); + }); + }; + + function _proc_exit(code) { + if (ENVIRONMENT_IS_PTHREAD) + return proxyToMainThread(0, 0, 1, code); + + EXITSTATUS = code; + if (!keepRuntimeAlive()) { + PThread.terminateAllThreads(); + Module['onExit']?.(code); + ABORT = true; + } + quit_(code, new ExitStatus(code)); + + } + + + /** @suppress {duplicate } */ + /** @param {boolean|number=} implicit */ + var exitJS = (status, implicit) => { + EXITSTATUS = status; + + checkUnflushedContent(); + + if (ENVIRONMENT_IS_PTHREAD) { + // implicit exit can never happen on a pthread + assert(!implicit); + // When running in a pthread we propagate the exit back to the main thread + // where it can decide if the whole process should be shut down or not. + // The pthread may have decided not to exit its own runtime, for example + // because it runs a main loop, but that doesn't affect the main thread. + exitOnMainThread(status); + throw 'unwind'; + } + + // if exit() was called explicitly, warn the user if the runtime isn't actually being shut down + if (keepRuntimeAlive() && !implicit) { + var msg = `program exited (with status: ${status}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`; + err(msg); + } + + _proc_exit(status); + }; + var _exit = exitJS; + + var ptrToString = (ptr) => { + assert(typeof ptr === 'number'); + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + ptr >>>= 0; + return '0x' + ptr.toString(16).padStart(8, '0'); + }; + + var handleException = (e) => { + // Certain exception types we do not treat as errors since they are used for + // internal control flow. + // 1. ExitStatus, which is thrown by exit() + // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others + // that wish to return to JS event loop. + if (e instanceof ExitStatus || e == 'unwind') { + return EXITSTATUS; + } + checkStackCookie(); + if (e instanceof WebAssembly.RuntimeError) { + if (_emscripten_stack_get_current() <= 0) { + err('Stack overflow detected. You can try increasing -sSTACK_SIZE (currently set to 65536)'); + } + } + quit_(1, e); + }; + + var PThread = { + unusedWorkers:[], + runningWorkers:[], + tlsInitFunctions:[], + pthreads:{ + }, + nextWorkerID:1, + debugInit() { + function pthreadLogPrefix() { + var t = 0; + if (runtimeInitialized && typeof _pthread_self != 'undefined' + ) { + t = _pthread_self(); + } + return 'w:' + (Module['workerID'] || 0) + ',t:' + ptrToString(t) + ': '; + } + + // Prefix all err()/dbg() messages with the calling thread ID. + var origDbg = dbg; + dbg = (...args) => origDbg(pthreadLogPrefix() + args.join(' ')); + }, + init() { + PThread.debugInit(); + if (ENVIRONMENT_IS_PTHREAD + ) { + PThread.initWorker(); + } else { + PThread.initMainThread(); + } + }, + initMainThread() { + // MINIMAL_RUNTIME takes care of calling loadWasmModuleToAllWorkers + // in postamble_minimal.js + addOnPreRun(() => { + addRunDependency('loading-workers') + PThread.loadWasmModuleToAllWorkers(() => removeRunDependency('loading-workers')); + }); + }, + initWorker() { + // worker.js is not compiled together with us, and must access certain + // things. + PThread['receiveObjectTransfer'] = PThread.receiveObjectTransfer; + PThread['threadInitTLS'] = PThread.threadInitTLS; + PThread['setExitStatus'] = PThread.setExitStatus; + + // The default behaviour for pthreads is always to exit once they return + // from their entry point (or call pthread_exit). If we set noExitRuntime + // to true here on pthreads they would never complete and attempt to + // pthread_join to them would block forever. + // pthreads can still choose to set `noExitRuntime` explicitly, or + // call emscripten_unwind_to_js_event_loop to extend their lifetime beyond + // their main function. See comment in src/worker.js for more. + noExitRuntime = false; + }, + setExitStatus:(status) => EXITSTATUS = status, + terminateAllThreads__deps:["$terminateWorker"], + terminateAllThreads:() => { + assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! terminateAllThreads() can only ever be called from main application thread!'); + // Attempt to kill all workers. Sadly (at least on the web) there is no + // way to terminate a worker synchronously, or to be notified when a + // worker in actually terminated. This means there is some risk that + // pthreads will continue to be executing after `worker.terminate` has + // returned. For this reason, we don't call `returnWorkerToPool` here or + // free the underlying pthread data structures. + for (var worker of PThread.runningWorkers) { + terminateWorker(worker); + } + for (var worker of PThread.unusedWorkers) { + terminateWorker(worker); + } + PThread.unusedWorkers = []; + PThread.runningWorkers = []; + PThread.pthreads = []; + }, + returnWorkerToPool:(worker) => { + // We don't want to run main thread queued calls here, since we are doing + // some operations that leave the worker queue in an invalid state until + // we are completely done (it would be bad if free() ends up calling a + // queued pthread_create which looks at the global data structures we are + // modifying). To achieve that, defer the free() til the very end, when + // we are all done. + var pthread_ptr = worker.pthread_ptr; + delete PThread.pthreads[pthread_ptr]; + // Note: worker is intentionally not terminated so the pool can + // dynamically grow. + PThread.unusedWorkers.push(worker); + PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker), 1); + // Not a running Worker anymore + // Detach the worker from the pthread object, and return it to the + // worker pool as an unused worker. + worker.pthread_ptr = 0; + + // Finally, free the underlying (and now-unused) pthread structure in + // linear memory. + __emscripten_thread_free_data(pthread_ptr); + }, + receiveObjectTransfer(data) { + }, + threadInitTLS() { + // Call thread init functions (these are the _emscripten_tls_init for each + // module loaded. + PThread.tlsInitFunctions.forEach((f) => f()); + }, + loadWasmModuleToWorker:(worker) => new Promise((onFinishedLoading) => { + worker.onmessage = (e) => { + var d = e['data']; + var cmd = d['cmd']; + + // If this message is intended to a recipient that is not the main + // thread, forward it to the target thread. + if (d['targetThread'] && d['targetThread'] != _pthread_self()) { + var targetWorker = PThread.pthreads[d['targetThread']]; + if (targetWorker) { + targetWorker.postMessage(d, d['transferList']); + } else { + err(`Internal error! Worker sent a message "${cmd}" to target pthread ${d['targetThread']}, but that thread no longer exists!`); + } + return; + } + + if (cmd === 'checkMailbox') { + checkMailbox(); + } else if (cmd === 'spawnThread') { + spawnThread(d); + } else if (cmd === 'cleanupThread') { + cleanupThread(d['thread']); + } else if (cmd === 'killThread') { + killThread(d['thread']); + } else if (cmd === 'cancelThread') { + cancelThread(d['thread']); + } else if (cmd === 'loaded') { + worker.loaded = true; + onFinishedLoading(worker); + } else if (cmd === 'alert') { + alert(`Thread ${d['threadId']}: ${d['text']}`); + } else if (d.target === 'setimmediate') { + // Worker wants to postMessage() to itself to implement setImmediate() + // emulation. + worker.postMessage(d); + } else if (cmd === 'callHandler') { + Module[d['handler']](...d['args']); + } else if (cmd) { + // The received message looks like something that should be handled by this message + // handler, (since there is a e.data.cmd field present), but is not one of the + // recognized commands: + err(`worker sent an unknown command ${cmd}`); + } + }; + + worker.onerror = (e) => { + var message = 'worker sent an error!'; + if (worker.pthread_ptr) { + message = `Pthread ${ptrToString(worker.pthread_ptr)} sent an error!`; + } + err(`${message} ${e.filename}:${e.lineno}: ${e.message}`); + throw e; + }; + + if (ENVIRONMENT_IS_NODE) { + worker.on('message', (data) => worker.onmessage({ data: data })); + worker.on('error', (e) => worker.onerror(e)); + } + + assert(wasmMemory instanceof WebAssembly.Memory, 'WebAssembly memory should have been loaded by now!'); + assert(wasmModule instanceof WebAssembly.Module, 'WebAssembly Module should have been loaded by now!'); + + // When running on a pthread, none of the incoming parameters on the module + // object are present. Proxy known handlers back to the main thread if specified. + var handlers = []; + var knownHandlers = [ + 'onExit', + 'onAbort', + 'print', + 'printErr', + ]; + for (var handler of knownHandlers) { + if (Module.hasOwnProperty(handler)) { + handlers.push(handler); + } + } + + worker.workerID = PThread.nextWorkerID++; + + // Ask the new worker to load up the Emscripten-compiled page. This is a heavy operation. + worker.postMessage({ + 'cmd': 'load', + 'handlers': handlers, + // If the application main .js file was loaded from a Blob, then it is not possible + // to access the URL of the current script that could be passed to a Web Worker so that + // it could load up the same file. In that case, developer must either deliver the Blob + // object in Module['mainScriptUrlOrBlob'], or a URL to it, so that pthread Workers can + // independently load up the same main application file. + 'urlOrBlob': Module['mainScriptUrlOrBlob'] + || _scriptDir + , + 'wasmMemory': wasmMemory, + 'wasmModule': wasmModule, + 'workerID': worker.workerID, + }); + }), + loadWasmModuleToAllWorkers(onMaybeReady) { + onMaybeReady(); + }, + allocateUnusedWorker() { + var worker; + // Allow HTML module to configure the location where the 'worker.js' file will be loaded from, + // via Module.locateFile() function. If not specified, then the default URL 'worker.js' relative + // to the main html file is loaded. + var pthreadMainJs = locateFile('convex_hull.worker.js'); + worker = new Worker(pthreadMainJs); + PThread.unusedWorkers.push(worker); + }, + getNewWorker() { + if (PThread.unusedWorkers.length == 0) { + // PTHREAD_POOL_SIZE_STRICT should show a warning and, if set to level `2`, return from the function. + // However, if we're in Node.js, then we can create new workers on the fly and PTHREAD_POOL_SIZE_STRICT + // should be ignored altogether. + if (!ENVIRONMENT_IS_NODE) { + err('Tried to spawn a new thread, but the thread pool is exhausted.\n' + + 'This might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.\n' + + 'If you want to increase the pool size, use setting `-sPTHREAD_POOL_SIZE=...`.' + + '\nIf you want to throw an explicit error instead of the risk of deadlocking in those cases, use setting `-sPTHREAD_POOL_SIZE_STRICT=2`.' + ); + } + PThread.allocateUnusedWorker(); + PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]); + } + return PThread.unusedWorkers.pop(); + }, + }; + Module['PThread'] = PThread; + + var callRuntimeCallbacks = (callbacks) => { + while (callbacks.length > 0) { + // Pass the module as the first argument. + callbacks.shift()(Module); + } + }; + + + var establishStackSpace = () => { + var pthread_ptr = _pthread_self(); + var stackHigh = HEAPU32[(((pthread_ptr)+(52))>>2)]; + var stackSize = HEAPU32[(((pthread_ptr)+(56))>>2)]; + var stackLow = stackHigh - stackSize; + assert(stackHigh != 0); + assert(stackLow != 0); + assert(stackHigh > stackLow, 'stackHigh must be higher then stackLow'); + // Set stack limits used by `emscripten/stack.h` function. These limits are + // cached in wasm-side globals to make checks as fast as possible. + _emscripten_stack_set_limits(stackHigh, stackLow); + + // Call inside wasm module to set up the stack frame for this pthread in wasm module scope + stackRestore(stackHigh); + + // Write the stack cookie last, after we have set up the proper bounds and + // current position of the stack. + writeStackCookie(); + }; + Module['establishStackSpace'] = establishStackSpace; + + + + + + function exitOnMainThread(returnCode) { + if (ENVIRONMENT_IS_PTHREAD) + return proxyToMainThread(1, 0, 0, returnCode); + + _exit(returnCode); + + } + + + + /** + * @param {number} ptr + * @param {string} type + */ + function getValue(ptr, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': return HEAP8[ptr]; + case 'i8': return HEAP8[ptr]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': abort('to do getValue(i64) use WASM_BIGINT'); + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + case '*': return HEAPU32[((ptr)>>2)]; + default: abort(`invalid type for getValue: ${type}`); + } + } + Module['getValue'] = getValue; + + + + + var wasmTableMirror = []; + + var wasmTable; + var getWasmTableEntry = (funcPtr) => { + var func = wasmTableMirror[funcPtr]; + if (!func) { + if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1; + wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr); + } + assert(wasmTable.get(funcPtr) == func, 'JavaScript-side Wasm function table mirror is out of date!'); + return func; + }; + var invokeEntryPoint = (ptr, arg) => { + + // pthread entry points are always of signature 'void *ThreadMain(void *arg)' + // Native codebases sometimes spawn threads with other thread entry point + // signatures, such as void ThreadMain(void *arg), void *ThreadMain(), or + // void ThreadMain(). That is not acceptable per C/C++ specification, but + // x86 compiler ABI extensions enable that to work. If you find the + // following line to crash, either change the signature to "proper" void + // *ThreadMain(void *arg) form, or try linking with the Emscripten linker + // flag -sEMULATE_FUNCTION_POINTER_CASTS to add in emulation for this x86 + // ABI extension. + var result = getWasmTableEntry(ptr)(arg); + checkStackCookie(); + function finish(result) { + if (keepRuntimeAlive()) { + PThread.setExitStatus(result); + } else { + __emscripten_thread_exit(result); + } + } + finish(result); + }; + Module['invokeEntryPoint'] = invokeEntryPoint; + + var noExitRuntime = Module['noExitRuntime'] || true; + + + var registerTLSInit = (tlsInitFunc) => PThread.tlsInitFunctions.push(tlsInitFunc); + + + /** + * @param {number} ptr + * @param {number} value + * @param {string} type + */ + function setValue(ptr, value, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': HEAP8[ptr] = value; break; + case 'i8': HEAP8[ptr] = value; break; + case 'i16': HEAP16[((ptr)>>1)] = value; break; + case 'i32': HEAP32[((ptr)>>2)] = value; break; + case 'i64': abort('to do setValue(i64) use WASM_BIGINT'); + case 'float': HEAPF32[((ptr)>>2)] = value; break; + case 'double': HEAPF64[((ptr)>>3)] = value; break; + case '*': HEAPU32[((ptr)>>2)] = value; break; + default: abort(`invalid type for setValue: ${type}`); + } + } + Module['setValue'] = setValue; + + var warnOnce = (text) => { + warnOnce.shown ||= {}; + if (!warnOnce.shown[text]) { + warnOnce.shown[text] = 1; + if (ENVIRONMENT_IS_NODE) text = 'warning: ' + text; + err(text); + } + }; + + var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined; + + /** + * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given + * array that contains uint8 values, returns a copy of that string as a + * Javascript String object. + * heapOrArray is either a regular array, or a JavaScript typed array view. + * @param {number} idx + * @param {number=} maxBytesToRead + * @return {string} + */ + var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => { + var endIdx = idx + maxBytesToRead; + var endPtr = idx; + // TextDecoder needs to know the byte length in advance, it doesn't stop on + // null terminator by itself. Also, use the length info to avoid running tiny + // strings through TextDecoder, since .subarray() allocates garbage. + // (As a tiny code save trick, compare endPtr against endIdx using a negation, + // so that undefined means Infinity) + while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; + + if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { + return UTF8Decoder.decode(heapOrArray.buffer instanceof SharedArrayBuffer ? heapOrArray.slice(idx, endPtr) : heapOrArray.subarray(idx, endPtr)); + } + var str = ''; + // If building with TextDecoder, we have already computed the string length + // above, so test loop end condition against that + while (idx < endPtr) { + // For UTF8 byte structure, see: + // http://en.wikipedia.org/wiki/UTF-8#Description + // https://www.ietf.org/rfc/rfc2279.txt + // https://tools.ietf.org/html/rfc3629 + var u0 = heapOrArray[idx++]; + if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } + var u1 = heapOrArray[idx++] & 63; + if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } + var u2 = heapOrArray[idx++] & 63; + if ((u0 & 0xF0) == 0xE0) { + u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; + } else { + if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!'); + u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); + } + + if (u0 < 0x10000) { + str += String.fromCharCode(u0); + } else { + var ch = u0 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } + } + return str; + }; + + /** + * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the + * emscripten HEAP, returns a copy of that string as a Javascript String object. + * + * @param {number} ptr + * @param {number=} maxBytesToRead - An optional length that specifies the + * maximum number of bytes to read. You can omit this parameter to scan the + * string until the first 0 byte. If maxBytesToRead is passed, and the string + * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the + * string will cut short at that byte index (i.e. maxBytesToRead will not + * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing + * frequent uses of UTF8ToString() with and without maxBytesToRead may throw + * JS JIT optimizations off, so it is worth to consider consistently using one + * @return {string} + */ + var UTF8ToString = (ptr, maxBytesToRead) => { + assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`); + return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; + }; + var ___assert_fail = (condition, filename, line, func) => { + abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); + }; + + var ___emscripten_init_main_thread_js = (tb) => { + // Pass the thread address to the native code where they stored in wasm + // globals which act as a form of TLS. Global constructors trying + // to access this value will read the wrong value, but that is UB anyway. + __emscripten_thread_init( + tb, + /*is_main=*/!ENVIRONMENT_IS_WORKER, + /*is_runtime=*/1, + /*can_block=*/!ENVIRONMENT_IS_WEB, + /*default_stacksize=*/65536, + /*start_profiling=*/false, + ); + PThread.threadInitTLS(); + }; + + var ___emscripten_thread_cleanup = (thread) => { + // Called when a thread needs to be cleaned up so it can be reused. + // A thread is considered reusable when it either returns from its + // entry point, calls pthread_exit, or acts upon a cancellation. + // Detached threads are responsible for calling this themselves, + // otherwise pthread_join is responsible for calling this. + if (!ENVIRONMENT_IS_PTHREAD) cleanupThread(thread); + else postMessage({ 'cmd': 'cleanupThread', 'thread': thread }); + }; + + var nowIsMonotonic = 1; + var __emscripten_get_now_is_monotonic = () => nowIsMonotonic; + + + + + + var maybeExit = () => { + if (!keepRuntimeAlive()) { + try { + if (ENVIRONMENT_IS_PTHREAD) __emscripten_thread_exit(EXITSTATUS); + else + _exit(EXITSTATUS); + } catch (e) { + handleException(e); + } + } + }; + var callUserCallback = (func) => { + if (ABORT) { + err('user callback triggered after runtime exited or application aborted. Ignoring.'); + return; + } + try { + func(); + maybeExit(); + } catch (e) { + handleException(e); + } + }; + + + + var __emscripten_thread_mailbox_await = (pthread_ptr) => { + if (typeof Atomics.waitAsync === 'function') { + // Wait on the pthread's initial self-pointer field because it is easy and + // safe to access from sending threads that need to notify the waiting + // thread. + // TODO: How to make this work with wasm64? + var wait = Atomics.waitAsync(HEAP32, ((pthread_ptr)>>2), pthread_ptr); + assert(wait.async); + wait.value.then(checkMailbox); + var waitingAsync = pthread_ptr + 128; + Atomics.store(HEAP32, ((waitingAsync)>>2), 1); + } + // If `Atomics.waitAsync` is not implemented, then we will always fall back + // to postMessage and there is no need to do anything here. + }; + Module['__emscripten_thread_mailbox_await'] = __emscripten_thread_mailbox_await; + + var checkMailbox = () => { + // Only check the mailbox if we have a live pthread runtime. We implement + // pthread_self to return 0 if there is no live runtime. + var pthread_ptr = _pthread_self(); + if (pthread_ptr) { + // If we are using Atomics.waitAsync as our notification mechanism, wait + // for a notification before processing the mailbox to avoid missing any + // work that could otherwise arrive after we've finished processing the + // mailbox and before we're ready for the next notification. + __emscripten_thread_mailbox_await(pthread_ptr); + callUserCallback(__emscripten_check_mailbox); + } + }; + Module['checkMailbox'] = checkMailbox; + + var __emscripten_notify_mailbox_postmessage = (targetThreadId, currThreadId, mainThreadId) => { + if (targetThreadId == currThreadId) { + setTimeout(checkMailbox); + } else if (ENVIRONMENT_IS_PTHREAD) { + postMessage({'targetThread' : targetThreadId, 'cmd' : 'checkMailbox'}); + } else { + var worker = PThread.pthreads[targetThreadId]; + if (!worker) { + err(`Cannot send message to thread with ID ${targetThreadId}, unknown thread ID!`); + return; + } + worker.postMessage({'cmd' : 'checkMailbox'}); + } + }; + + + var proxiedJSCallArgs = []; + + var __emscripten_receive_on_main_thread_js = (funcIndex, emAsmAddr, callingThread, numCallArgs, args) => { + // Sometimes we need to backproxy events to the calling thread (e.g. + // HTML5 DOM events handlers such as + // emscripten_set_mousemove_callback()), so keep track in a globally + // accessible variable about the thread that initiated the proxying. + proxiedJSCallArgs.length = numCallArgs; + var b = ((args)>>3); + for (var i = 0; i < numCallArgs; i++) { + proxiedJSCallArgs[i] = HEAPF64[b + i]; + } + // Proxied JS library funcs use funcIndex and EM_ASM functions use emAsmAddr + assert(!emAsmAddr); + var func = proxiedFunctionTable[funcIndex]; + assert(!(funcIndex && emAsmAddr)); + assert(func.length == numCallArgs, 'Call args mismatch in _emscripten_receive_on_main_thread_js'); + PThread.currentProxiedOperationCallerThread = callingThread; + var rtn = func(...proxiedJSCallArgs); + PThread.currentProxiedOperationCallerThread = 0; + // Proxied functions can return any type except bigint. All other types + // cooerce to f64/double (the return type of this function in C) but not + // bigint. + assert(typeof rtn != "bigint"); + return rtn; + }; + + + var __emscripten_thread_set_strongref = (thread) => { + // Called when a thread needs to be strongly referenced. + // Currently only used for: + // - keeping the "main" thread alive in PROXY_TO_PTHREAD mode; + // - crashed threads that needs to propagate the uncaught exception + // back to the main thread. + if (ENVIRONMENT_IS_NODE) { + PThread.pthreads[thread].ref(); + } + }; + + + var _emscripten_check_blocking_allowed = () => { + if (ENVIRONMENT_IS_NODE) return; + + if (ENVIRONMENT_IS_WORKER) return; // Blocking in a worker/pthread is fine. + + warnOnce('Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread'); + + }; + + var _emscripten_date_now = () => Date.now(); + + var runtimeKeepalivePush = () => { + runtimeKeepaliveCounter += 1; + }; + var _emscripten_exit_with_live_runtime = () => { + runtimeKeepalivePush(); + throw 'unwind'; + }; + + var _emscripten_get_now; + // Pthreads need their clocks synchronized to the execution of the main + // thread, so, when using them, make sure to adjust all timings to the + // respective time origins. + _emscripten_get_now = () => performance.timeOrigin + performance.now(); + ; + + var getHeapMax = () => + HEAPU8.length; + + var abortOnCannotGrowMemory = (requestedSize) => { + abort(`Cannot enlarge memory arrays to size ${requestedSize} bytes (OOM). Either (1) compile with -sINITIAL_MEMORY=X with X higher than the current value ${HEAP8.length}, (2) compile with -sALLOW_MEMORY_GROWTH which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -sABORTING_MALLOC=0`); + }; + var _emscripten_resize_heap = (requestedSize) => { + var oldSize = HEAPU8.length; + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + requestedSize >>>= 0; + abortOnCannotGrowMemory(requestedSize); + }; + + + var printCharBuffers = [null,[],[]]; + + var printChar = (stream, curr) => { + var buffer = printCharBuffers[stream]; + assert(buffer); + if (curr === 0 || curr === 10) { + (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0)); + buffer.length = 0; + } else { + buffer.push(curr); + } + }; + + var flush_NO_FILESYSTEM = () => { + // flush anything remaining in the buffers during shutdown + _fflush(0); + if (printCharBuffers[1].length) printChar(1, 10); + if (printCharBuffers[2].length) printChar(2, 10); + }; + + + var SYSCALLS = { + varargs:undefined, + get() { + assert(SYSCALLS.varargs != undefined); + // the `+` prepended here is necessary to convince the JSCompiler that varargs is indeed a number. + var ret = HEAP32[((+SYSCALLS.varargs)>>2)]; + SYSCALLS.varargs += 4; + return ret; + }, + getp() { return SYSCALLS.get() }, + getStr(ptr) { + var ret = UTF8ToString(ptr); + return ret; + }, + }; + + + function _fd_write(fd, iov, iovcnt, pnum) { + if (ENVIRONMENT_IS_PTHREAD) + return proxyToMainThread(2, 0, 1, fd, iov, iovcnt, pnum); + + // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0 + var num = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + for (var j = 0; j < len; j++) { + printChar(fd, HEAPU8[ptr+j]); + } + num += len; + } + HEAPU32[((pnum)>>2)] = num; + return 0; + + } + + + var getCFunc = (ident) => { + var func = Module['_' + ident]; // closure exported function + assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported'); + return func; + }; + + var writeArrayToMemory = (array, buffer) => { + assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)') + HEAP8.set(array, buffer); + }; + + var lengthBytesUTF8 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var c = str.charCodeAt(i); // possibly a lead surrogate + if (c <= 0x7F) { + len++; + } else if (c <= 0x7FF) { + len += 2; + } else if (c >= 0xD800 && c <= 0xDFFF) { + len += 4; ++i; + } else { + len += 3; + } + } + return len; + }; + + var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { + assert(typeof str === 'string', `stringToUTF8Array expects a string (got ${typeof str})`); + // Parameter maxBytesToWrite is not optional. Negative values, 0, null, + // undefined and false each don't write out any bytes. + if (!(maxBytesToWrite > 0)) + return 0; + + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description + // and https://www.ietf.org/rfc/rfc2279.txt + // and https://tools.ietf.org/html/rfc3629 + var u = str.charCodeAt(i); // possibly a lead surrogate + if (u >= 0xD800 && u <= 0xDFFF) { + var u1 = str.charCodeAt(++i); + u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF); + } + if (u <= 0x7F) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u; + } else if (u <= 0x7FF) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 0xC0 | (u >> 6); + heap[outIdx++] = 0x80 | (u & 63); + } else if (u <= 0xFFFF) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 0xE0 | (u >> 12); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } else { + if (outIdx + 3 >= endIdx) break; + if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).'); + heap[outIdx++] = 0xF0 | (u >> 18); + heap[outIdx++] = 0x80 | ((u >> 12) & 63); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } + } + // Null-terminate the pointer to the buffer. + heap[outIdx] = 0; + return outIdx - startIdx; + }; + var stringToUTF8 = (str, outPtr, maxBytesToWrite) => { + assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); + return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); + }; + var stringToUTF8OnStack = (str) => { + var size = lengthBytesUTF8(str) + 1; + var ret = stackAlloc(size); + stringToUTF8(str, ret, size); + return ret; + }; + + + + + + /** + * @param {string|null=} returnType + * @param {Array=} argTypes + * @param {Arguments|Array=} args + * @param {Object=} opts + */ + var ccall = (ident, returnType, argTypes, args, opts) => { + // For fast lookup of conversion functions + var toC = { + 'string': (str) => { + var ret = 0; + if (str !== null && str !== undefined && str !== 0) { // null string + // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' + ret = stringToUTF8OnStack(str); + } + return ret; + }, + 'array': (arr) => { + var ret = stackAlloc(arr.length); + writeArrayToMemory(arr, ret); + return ret; + } + }; + + function convertReturnValue(ret) { + if (returnType === 'string') { + + return UTF8ToString(ret); + } + if (returnType === 'boolean') return Boolean(ret); + return ret; + } + + var func = getCFunc(ident); + var cArgs = []; + var stack = 0; + assert(returnType !== 'array', 'Return type should not be "array".'); + if (args) { + for (var i = 0; i < args.length; i++) { + var converter = toC[argTypes[i]]; + if (converter) { + if (stack === 0) stack = stackSave(); + cArgs[i] = converter(args[i]); + } else { + cArgs[i] = args[i]; + } + } + } + var ret = func(...cArgs); + function onDone(ret) { + if (stack !== 0) stackRestore(stack); + return convertReturnValue(ret); + } + + ret = onDone(ret); + return ret; + }; + + + + /** + * @param {string=} returnType + * @param {Array=} argTypes + * @param {Object=} opts + */ + var cwrap = (ident, returnType, argTypes, opts) => { + return (...args) => ccall(ident, returnType, argTypes, args, opts); + }; + + +PThread.init();; + +// proxiedFunctionTable specifies the list of functions that can be called +// either synchronously or asynchronously from other threads in postMessage()d +// or internally queued events. This way a pthread in a Worker can synchronously +// access e.g. the DOM on the main thread. +var proxiedFunctionTable = [ + _proc_exit, + exitOnMainThread, + _fd_write +]; + +function checkIncomingModuleAPI() { + ignoredModuleProp('fetchSettings'); +} +var wasmImports = { + /** @export */ + __assert_fail: ___assert_fail, + /** @export */ + __emscripten_init_main_thread_js: ___emscripten_init_main_thread_js, + /** @export */ + __emscripten_thread_cleanup: ___emscripten_thread_cleanup, + /** @export */ + _emscripten_get_now_is_monotonic: __emscripten_get_now_is_monotonic, + /** @export */ + _emscripten_notify_mailbox_postmessage: __emscripten_notify_mailbox_postmessage, + /** @export */ + _emscripten_receive_on_main_thread_js: __emscripten_receive_on_main_thread_js, + /** @export */ + _emscripten_thread_mailbox_await: __emscripten_thread_mailbox_await, + /** @export */ + _emscripten_thread_set_strongref: __emscripten_thread_set_strongref, + /** @export */ + emscripten_check_blocking_allowed: _emscripten_check_blocking_allowed, + /** @export */ + emscripten_date_now: _emscripten_date_now, + /** @export */ + emscripten_exit_with_live_runtime: _emscripten_exit_with_live_runtime, + /** @export */ + emscripten_get_now: _emscripten_get_now, + /** @export */ + emscripten_resize_heap: _emscripten_resize_heap, + /** @export */ + exit: _exit, + /** @export */ + fd_write: _fd_write, + /** @export */ + memory: wasmMemory +}; +var wasmExports = createWasm(); +var ___wasm_call_ctors = createExportWrapper('__wasm_call_ctors'); +var _convexHull = Module['_convexHull'] = createExportWrapper('convexHull'); +var __emscripten_tls_init = Module['__emscripten_tls_init'] = createExportWrapper('_emscripten_tls_init'); +var _pthread_self = Module['_pthread_self'] = () => (_pthread_self = Module['_pthread_self'] = wasmExports['pthread_self'])(); +var __emscripten_thread_init = Module['__emscripten_thread_init'] = createExportWrapper('_emscripten_thread_init'); +var __emscripten_thread_crashed = Module['__emscripten_thread_crashed'] = createExportWrapper('_emscripten_thread_crashed'); +var _fflush = createExportWrapper('fflush'); +var _emscripten_main_runtime_thread_id = createExportWrapper('emscripten_main_runtime_thread_id'); +var _emscripten_main_thread_process_queued_calls = createExportWrapper('emscripten_main_thread_process_queued_calls'); +var __emscripten_run_on_main_thread_js = createExportWrapper('_emscripten_run_on_main_thread_js'); +var __emscripten_thread_free_data = createExportWrapper('_emscripten_thread_free_data'); +var __emscripten_thread_exit = Module['__emscripten_thread_exit'] = createExportWrapper('_emscripten_thread_exit'); +var __emscripten_check_mailbox = createExportWrapper('_emscripten_check_mailbox'); +var _malloc = Module['_malloc'] = createExportWrapper('malloc'); +var _free = Module['_free'] = createExportWrapper('free'); +var _emscripten_stack_get_base = () => (_emscripten_stack_get_base = wasmExports['emscripten_stack_get_base'])(); +var _emscripten_stack_get_end = () => (_emscripten_stack_get_end = wasmExports['emscripten_stack_get_end'])(); +var _emscripten_stack_init = () => (_emscripten_stack_init = wasmExports['emscripten_stack_init'])(); +var _emscripten_stack_set_limits = (a0, a1) => (_emscripten_stack_set_limits = wasmExports['emscripten_stack_set_limits'])(a0, a1); +var _emscripten_stack_get_free = () => (_emscripten_stack_get_free = wasmExports['emscripten_stack_get_free'])(); +var stackSave = createExportWrapper('stackSave'); +var stackRestore = createExportWrapper('stackRestore'); +var stackAlloc = createExportWrapper('stackAlloc'); +var _emscripten_stack_get_current = () => (_emscripten_stack_get_current = wasmExports['emscripten_stack_get_current'])(); +var dynCall_jiji = Module['dynCall_jiji'] = createExportWrapper('dynCall_jiji'); + + +// include: postamble.js +// === Auto-generated postamble setup entry stuff === + +Module['wasmMemory'] = wasmMemory; +Module['keepRuntimeAlive'] = keepRuntimeAlive; +Module['ccall'] = ccall; +Module['cwrap'] = cwrap; +Module['ExitStatus'] = ExitStatus; +var missingLibrarySymbols = [ + 'writeI53ToI64', + 'writeI53ToI64Clamped', + 'writeI53ToI64Signaling', + 'writeI53ToU64Clamped', + 'writeI53ToU64Signaling', + 'readI53FromI64', + 'readI53FromU64', + 'convertI32PairToI53', + 'convertU32PairToI53', + 'growMemory', + 'isLeapYear', + 'ydayFromDate', + 'arraySum', + 'addDays', + 'inetPton4', + 'inetNtop4', + 'inetPton6', + 'inetNtop6', + 'readSockaddr', + 'writeSockaddr', + 'initRandomFill', + 'randomFill', + 'getCallstack', + 'emscriptenLog', + 'convertPCtoSourceLocation', + 'readEmAsmArgs', + 'jstoi_q', + 'getExecutableName', + 'listenOnce', + 'autoResumeAudioContext', + 'dynCallLegacy', + 'getDynCaller', + 'dynCall', + 'runtimeKeepalivePop', + 'asmjsMangle', + 'asyncLoad', + 'alignMemory', + 'mmapAlloc', + 'HandleAllocator', + 'getNativeTypeSize', + 'STACK_SIZE', + 'STACK_ALIGN', + 'POINTER_SIZE', + 'ASSERTIONS', + 'uleb128Encode', + 'sigToWasmTypes', + 'generateFuncType', + 'convertJsFunctionToWasm', + 'getEmptyTableSlot', + 'updateTableMap', + 'getFunctionAddress', + 'addFunction', + 'removeFunction', + 'reallyNegative', + 'unSign', + 'strLen', + 'reSign', + 'formatString', + 'intArrayFromString', + 'intArrayToString', + 'AsciiToString', + 'stringToAscii', + 'UTF16ToString', + 'stringToUTF16', + 'lengthBytesUTF16', + 'UTF32ToString', + 'stringToUTF32', + 'lengthBytesUTF32', + 'stringToNewUTF8', + 'registerKeyEventCallback', + 'maybeCStringToJsString', + 'findEventTarget', + 'getBoundingClientRect', + 'fillMouseEventData', + 'registerMouseEventCallback', + 'registerWheelEventCallback', + 'registerUiEventCallback', + 'registerFocusEventCallback', + 'fillDeviceOrientationEventData', + 'registerDeviceOrientationEventCallback', + 'fillDeviceMotionEventData', + 'registerDeviceMotionEventCallback', + 'screenOrientation', + 'fillOrientationChangeEventData', + 'registerOrientationChangeEventCallback', + 'fillFullscreenChangeEventData', + 'registerFullscreenChangeEventCallback', + 'JSEvents_requestFullscreen', + 'JSEvents_resizeCanvasForFullscreen', + 'registerRestoreOldStyle', + 'hideEverythingExceptGivenElement', + 'restoreHiddenElements', + 'setLetterbox', + 'softFullscreenResizeWebGLRenderTarget', + 'doRequestFullscreen', + 'fillPointerlockChangeEventData', + 'registerPointerlockChangeEventCallback', + 'registerPointerlockErrorEventCallback', + 'requestPointerLock', + 'fillVisibilityChangeEventData', + 'registerVisibilityChangeEventCallback', + 'registerTouchEventCallback', + 'fillGamepadEventData', + 'registerGamepadEventCallback', + 'registerBeforeUnloadEventCallback', + 'fillBatteryEventData', + 'battery', + 'registerBatteryEventCallback', + 'setCanvasElementSizeCallingThread', + 'setCanvasElementSizeMainThread', + 'setCanvasElementSize', + 'getCanvasSizeCallingThread', + 'getCanvasSizeMainThread', + 'getCanvasElementSize', + 'jsStackTrace', + 'stackTrace', + 'getEnvStrings', + 'checkWasiClock', + 'wasiRightsToMuslOFlags', + 'wasiOFlagsToMuslOFlags', + 'createDyncallWrapper', + 'safeSetTimeout', + 'setImmediateWrapped', + 'clearImmediateWrapped', + 'polyfillSetImmediate', + 'getPromise', + 'makePromise', + 'idsToPromises', + 'makePromiseCallback', + 'ExceptionInfo', + 'findMatchingCatch', + 'Browser_asyncPrepareDataCounter', + 'setMainLoop', + 'getSocketFromFD', + 'getSocketAddress', + 'FS_createPreloadedFile', + 'FS_modeStringToFlags', + 'FS_getMode', + 'FS_stdin_getChar', + 'FS_createDataFile', + 'FS_unlink', + 'FS_mkdirTree', + '_setNetworkCallback', + 'heapObjectForWebGLType', + 'toTypedArrayIndex', + 'webgl_enable_ANGLE_instanced_arrays', + 'webgl_enable_OES_vertex_array_object', + 'webgl_enable_WEBGL_draw_buffers', + 'webgl_enable_WEBGL_multi_draw', + 'emscriptenWebGLGet', + 'computeUnpackAlignedImageSize', + 'colorChannelsInGlTextureFormat', + 'emscriptenWebGLGetTexPixelData', + 'emscriptenWebGLGetUniform', + 'webglGetUniformLocation', + 'webglPrepareUniformLocationsBeforeFirstUse', + 'webglGetLeftBracePos', + 'emscriptenWebGLGetVertexAttrib', + '__glGetActiveAttribOrUniform', + 'writeGLArray', + 'emscripten_webgl_destroy_context_before_on_calling_thread', + 'registerWebGlEventCallback', + 'runAndAbortIfError', + 'ALLOC_NORMAL', + 'ALLOC_STACK', + 'allocate', + 'writeStringToMemory', + 'writeAsciiToMemory', + 'setErrNo', + 'demangle', +]; +missingLibrarySymbols.forEach(missingLibrarySymbol) + +var unexportedSymbols = [ + 'run', + 'addOnPreRun', + 'addOnInit', + 'addOnPreMain', + 'addOnExit', + 'addOnPostRun', + 'addRunDependency', + 'removeRunDependency', + 'FS_createFolder', + 'FS_createPath', + 'FS_createLazyFile', + 'FS_createLink', + 'FS_createDevice', + 'FS_readFile', + 'out', + 'err', + 'callMain', + 'abort', + 'wasmExports', + 'stackAlloc', + 'stackSave', + 'stackRestore', + 'getTempRet0', + 'setTempRet0', + 'writeStackCookie', + 'checkStackCookie', + 'convertI32PairToI53Checked', + 'ptrToString', + 'zeroMemory', + 'exitJS', + 'getHeapMax', + 'abortOnCannotGrowMemory', + 'ENV', + 'MONTH_DAYS_REGULAR', + 'MONTH_DAYS_LEAP', + 'MONTH_DAYS_REGULAR_CUMULATIVE', + 'MONTH_DAYS_LEAP_CUMULATIVE', + 'ERRNO_CODES', + 'ERRNO_MESSAGES', + 'DNS', + 'Protocols', + 'Sockets', + 'timers', + 'warnOnce', + 'UNWIND_CACHE', + 'readEmAsmArgsArray', + 'jstoi_s', + 'handleException', + 'runtimeKeepalivePush', + 'callUserCallback', + 'maybeExit', + 'wasmTable', + 'noExitRuntime', + 'getCFunc', + 'freeTableIndexes', + 'functionsInTableMap', + 'setValue', + 'getValue', + 'PATH', + 'PATH_FS', + 'UTF8Decoder', + 'UTF8ArrayToString', + 'UTF8ToString', + 'stringToUTF8Array', + 'stringToUTF8', + 'lengthBytesUTF8', + 'UTF16Decoder', + 'stringToUTF8OnStack', + 'writeArrayToMemory', + 'JSEvents', + 'specialHTMLTargets', + 'findCanvasEventTarget', + 'currentFullscreenStrategy', + 'restoreOldWindowedStyle', + 'flush_NO_FILESYSTEM', + 'promiseMap', + 'uncaughtExceptionCount', + 'exceptionLast', + 'exceptionCaught', + 'Browser', + 'getPreloadedImageData__data', + 'wget', + 'SYSCALLS', + 'preloadPlugins', + 'FS_stdin_getChar_buffer', + 'FS', + 'MEMFS', + 'TTY', + 'PIPEFS', + 'SOCKFS', + 'tempFixedLengthArray', + 'miniTempWebGLFloatBuffers', + 'miniTempWebGLIntBuffers', + 'GL', + 'AL', + 'GLUT', + 'EGL', + 'GLEW', + 'IDBStore', + 'SDL', + 'SDL_gfx', + 'allocateUTF8', + 'allocateUTF8OnStack', + 'PThread', + 'terminateWorker', + 'killThread', + 'cleanupThread', + 'registerTLSInit', + 'cancelThread', + 'spawnThread', + 'exitOnMainThread', + 'proxyToMainThread', + 'proxiedJSCallArgs', + 'invokeEntryPoint', + 'checkMailbox', +]; +unexportedSymbols.forEach(unexportedRuntimeSymbol); + + + +var calledRun; + +dependenciesFulfilled = function runCaller() { + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!calledRun) run(); + if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled +}; + +function stackCheckInit() { + // This is normally called automatically during __wasm_call_ctors but need to + // get these values before even running any of the ctors so we call it redundantly + // here. + // See $establishStackSpace for the equivalent code that runs on a thread + assert(!ENVIRONMENT_IS_PTHREAD); + _emscripten_stack_init(); + // TODO(sbc): Move writeStackCookie to native to to avoid this. + writeStackCookie(); +} + +function run() { + + if (runDependencies > 0) { + return; + } + + if (!ENVIRONMENT_IS_PTHREAD) + stackCheckInit(); + + if (ENVIRONMENT_IS_PTHREAD) { + initRuntime(); + startWorker(Module); + return; + } + + preRun(); + + // a preRun added a dependency, run will be called later + if (runDependencies > 0) { + return; + } + + function doRun() { + // run may have just been called through dependencies being fulfilled just in this very frame, + // or while the async setStatus time below was happening + if (calledRun) return; + calledRun = true; + Module['calledRun'] = true; + + if (ABORT) return; + + initRuntime(); + + if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); + + assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]'); + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + doRun(); + }, 1); + } else + { + doRun(); + } + checkStackCookie(); +} + +function checkUnflushedContent() { + // Compiler settings do not allow exiting the runtime, so flushing + // the streams is not possible. but in ASSERTIONS mode we check + // if there was something to flush, and if so tell the user they + // should request that the runtime be exitable. + // Normally we would not even include flush() at all, but in ASSERTIONS + // builds we do so just for this check, and here we see if there is any + // content to flush, that is, we check if there would have been + // something a non-ASSERTIONS build would have not seen. + // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0 + // mode (which has its own special function for this; otherwise, all + // the code is inside libc) + var oldOut = out; + var oldErr = err; + var has = false; + out = err = (x) => { + has = true; + } + try { // it doesn't matter if it fails + flush_NO_FILESYSTEM(); + } catch(e) {} + out = oldOut; + err = oldErr; + if (has) { + warnOnce('stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the Emscripten FAQ), or make sure to emit a newline when you printf etc.'); + warnOnce('(this may also be due to not including full filesystem support - try building with -sFORCE_FILESYSTEM)'); + } +} + +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} + +run(); + +// end include: postamble.js + diff --git a/convex_hull.wasm b/convex_hull.wasm new file mode 100755 index 0000000..2e48fdb Binary files /dev/null and b/convex_hull.wasm differ diff --git a/convex_hull.worker.js b/convex_hull.worker.js new file mode 100644 index 0000000..b14c0fa --- /dev/null +++ b/convex_hull.worker.js @@ -0,0 +1,196 @@ +/** + * @license + * Copyright 2015 The Emscripten Authors + * SPDX-License-Identifier: MIT + */ + +// Pthread Web Worker startup routine: +// This is the entry point file that is loaded first by each Web Worker +// that executes pthreads on the Emscripten application. + +'use strict'; + +var Module = {}; + +// Node.js support +var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string'; +if (ENVIRONMENT_IS_NODE) { + // Create as web-worker-like an environment as we can. + + // See the parallel code in shell.js, but here we don't need the condition on + // multi-environment builds, as we do not have the need to interact with the + // modularization logic as shell.js must (see link.py:node_es6_imports and + // how that is used in link.py). + + var nodeWorkerThreads = require('worker_threads'); + + var parentPort = nodeWorkerThreads.parentPort; + + parentPort.on('message', (data) => onmessage({ data: data })); + + var fs = require('fs'); + var vm = require('vm'); + + Object.assign(global, { + self: global, + require, + Module, + location: { + // __filename is undefined in ES6 modules, and import.meta.url only in ES6 + // modules. + href: __filename + }, + Worker: nodeWorkerThreads.Worker, + importScripts: (f) => vm.runInThisContext(fs.readFileSync(f, 'utf8'), {filename: f}), + postMessage: (msg) => parentPort.postMessage(msg), + performance: global.performance || { now: Date.now }, + }); +} + +// Thread-local guard variable for one-time init of the JS state +var initializedJS = false; + +function assert(condition, text) { + if (!condition) abort('Assertion failed: ' + text); +} + +function threadPrintErr(...args) { + var text = args.join(' '); + // See https://github.com/emscripten-core/emscripten/issues/14804 + if (ENVIRONMENT_IS_NODE) { + fs.writeSync(2, text + '\n'); + return; + } + console.error(text); +} +function threadAlert(...args) { + var text = args.join(' '); + postMessage({cmd: 'alert', text, threadId: Module['_pthread_self']()}); +} +// We don't need out() for now, but may need to add it if we want to use it +// here. Or, if this code all moves into the main JS, that problem will go +// away. (For now, adding it here increases code size for no benefit.) +var out = () => { throw 'out() is not defined in worker.js.'; } +var err = threadPrintErr; +self.alert = threadAlert; +var dbg = threadPrintErr; + +Module['instantiateWasm'] = (info, receiveInstance) => { + // Instantiate from the module posted from the main thread. + // We can just use sync instantiation in the worker. + var module = Module['wasmModule']; + // We don't need the module anymore; new threads will be spawned from the main thread. + Module['wasmModule'] = null; + var instance = new WebAssembly.Instance(module, info); + // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, + // the above line no longer optimizes out down to the following line. + // When the regression is fixed, we can remove this if/else. + return receiveInstance(instance); +} + +// Turn unhandled rejected promises into errors so that the main thread will be +// notified about them. +self.onunhandledrejection = (e) => { + throw e.reason || e; +}; + +function handleMessage(e) { + try { + if (e.data.cmd === 'load') { // Preload command that is called once per worker to parse and load the Emscripten code. + + // Until we initialize the runtime, queue up any further incoming messages. + let messageQueue = []; + self.onmessage = (e) => messageQueue.push(e); + + // And add a callback for when the runtime is initialized. + self.startWorker = (instance) => { + // Notify the main thread that this thread has loaded. + postMessage({ 'cmd': 'loaded' }); + // Process any messages that were queued before the thread was ready. + for (let msg of messageQueue) { + handleMessage(msg); + } + // Restore the real message handler. + self.onmessage = handleMessage; + }; + + // Module and memory were sent from main thread + Module['wasmModule'] = e.data.wasmModule; + + // Use `const` here to ensure that the variable is scoped only to + // that iteration, allowing safe reference from a closure. + for (const handler of e.data.handlers) { + Module[handler] = (...args) => { + postMessage({ cmd: 'callHandler', handler, args: args }); + } + } + + Module['wasmMemory'] = e.data.wasmMemory; + + Module['buffer'] = Module['wasmMemory'].buffer; + + Module['workerID'] = e.data.workerID; + + Module['ENVIRONMENT_IS_PTHREAD'] = true; + + if (typeof e.data.urlOrBlob == 'string') { + importScripts(e.data.urlOrBlob); + } else { + var objectUrl = URL.createObjectURL(e.data.urlOrBlob); + importScripts(objectUrl); + URL.revokeObjectURL(objectUrl); + } + } else if (e.data.cmd === 'run') { + // Pass the thread address to wasm to store it for fast access. + Module['__emscripten_thread_init'](e.data.pthread_ptr, /*is_main=*/0, /*is_runtime=*/0, /*can_block=*/1); + + // Await mailbox notifications with `Atomics.waitAsync` so we can start + // using the fast `Atomics.notify` notification path. + Module['__emscripten_thread_mailbox_await'](e.data.pthread_ptr); + + assert(e.data.pthread_ptr); + // Also call inside JS module to set up the stack frame for this pthread in JS module scope + Module['establishStackSpace'](); + Module['PThread'].receiveObjectTransfer(e.data); + Module['PThread'].threadInitTLS(); + + if (!initializedJS) { + initializedJS = true; + } + + try { + Module['invokeEntryPoint'](e.data.start_routine, e.data.arg); + } catch(ex) { + if (ex != 'unwind') { + // The pthread "crashed". Do not call `_emscripten_thread_exit` (which + // would make this thread joinable). Instead, re-throw the exception + // and let the top level handler propagate it back to the main thread. + throw ex; + } + } + } else if (e.data.cmd === 'cancel') { // Main thread is asking for a pthread_cancel() on this thread. + if (Module['_pthread_self']()) { + Module['__emscripten_thread_exit'](-1); + } + } else if (e.data.target === 'setimmediate') { + // no-op + } else if (e.data.cmd === 'checkMailbox') { + if (initializedJS) { + Module['checkMailbox'](); + } + } else if (e.data.cmd) { + // The received message looks like something that should be handled by this message + // handler, (since there is a e.data.cmd field present), but is not one of the + // recognized commands: + err(`worker.js received unknown command ${e.data.cmd}`); + err(e.data); + } + } catch(ex) { + err(`worker.js onmessage() captured an uncaught exception: ${ex}`); + if (ex?.stack) err(ex.stack); + Module['__emscripten_thread_crashed']?.(); + throw ex; + } +}; + +self.onmessage = handleMessage; diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..72a15a7 --- /dev/null +++ b/readme.md @@ -0,0 +1 @@ +凸包算法的wasm实现 \ No newline at end of file diff --git a/test.html b/test.html new file mode 100644 index 0000000..eb0f2b4 --- /dev/null +++ b/test.html @@ -0,0 +1,54 @@ + + \ No newline at end of file diff --git a/生成 b/生成 new file mode 100644 index 0000000..2f23279 --- /dev/null +++ b/生成 @@ -0,0 +1,3 @@ +docker run --rm -v $(pwd):/src emscripten/emsdk emcc convex_hull.c -o convex_hull.js -s IMPORTED_MEMORY=1 -s INITIAL_MEMORY=104857600 -s EXPORTED_FUNCTIONS="['_convexHull','_malloc','_free','setValue','getValue']" -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' + +docker run --rm -v $(pwd):/src emscripten/emsdk emcc convex_hull.c -o convex_hull.js -s USE_PTHREADS=1 -s IMPORTED_MEMORY=1 -s EXPORTED_FUNCTIONS="['_convexHull','_malloc','_free','setValue','getValue']" -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' \ No newline at end of file