| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 | 
const fs = require('fs');const TOTAL_STACK = 1024 * 1024; // 1MBconst TOTAL_MEMORY = 2 * 1024 * 1024; // 1MBconst WASM_PAGE_SIZE = 64 * 1024; // Defined in WebAssembly specsconst WASM_CODE = Buffer.from(require('./cephes.wasm.base64.json'), 'base64');class CephesWrapper {  constructor(sync) {    // Initialize the runtime's memory    this._wasmMemory = new WebAssembly.Memory({      'initial': TOTAL_MEMORY / WASM_PAGE_SIZE,      'maximum': TOTAL_MEMORY / WASM_PAGE_SIZE    });    this._HEAP8 = new Int8Array(this._wasmMemory.buffer);    this._HEAP16 = new Int16Array(this._wasmMemory.buffer);    this._HEAP32 = new Int32Array(this._wasmMemory.buffer);    this._HEAPF32 = new Float32Array(this._wasmMemory.buffer);    this._HEAPF64 = new Float64Array(this._wasmMemory.buffer);    // Compile and export program    if (sync) {      // compile synchronously      const program = this._compileSync();      this._exportProgram(program);      // create a dummy compile promise      this.compiled = Promise.resolve();    } else {      // create a singleton compile promise      this.compiled = this._compileAsync()        .then((program) => this._exportProgram(program));    }  }  _AsciiToString(ptr) {    let str = '';    while (1) {      const ch = this._HEAP8[((ptr++)>>0)];      if (ch === 0) return str;      str += String.fromCharCode(ch);    }  }  _mtherr(name /* char* */, code /* int */) {    // from mtherr.c    let codemsg = '';    switch (code) {      case 1: codemsg = 'argument domain error'; break;      case 2: codemsg = 'function singularity'; break;      case 3: codemsg = 'overflow range error'; break;      case 4: codemsg = 'underflow range error'; break;      case 5: codemsg = 'total loss of precision'; break;      case 6: codemsg = 'partial loss of precision'; break;      case 33: codemsg = 'Unix domain error code'; break;      case 34: codemsg = 'Unix range error code'; break;      default: codemsg = 'unknown error';    }    const fnname = this._AsciiToString(name);    const message = 'cephes reports "' + codemsg + '" in ' + fnname;    // Restore stack to the STACKTOP before throwing. This only works because    // all the exported cephes functions are plain functions.    this.stackRestore(0);    if (code == 1) {      throw new RangeError(message);    } else {      throw new Error(message);    }  }  _wasmImports() {    return {      'env': {        // cephes error handler        "_mtherr": this._mtherr.bind(this),        // memory        "memory": this._wasmMemory,        "STACKTOP": 0,        "STACK_MAX": TOTAL_STACK      }    };  }  _compileSync() {    return new WebAssembly.Instance(      new WebAssembly.Module(WASM_CODE),      this._wasmImports()    );  }  _compileAsync() {    return WebAssembly.instantiate(      WASM_CODE,      this._wasmImports()    ).then((results) => results.instance);  }  _exportProgram(program) {    // export cephes functions    for (const key of Object.keys(program.exports)) {      if (key.startsWith('_cephes_')) {        this[key] = program.exports[key];      }    }    // export special stack functions    this.stackAlloc = program.exports.stackAlloc;    this.stackRestore = program.exports.stackRestore;    this.stackSave = program.exports.stackSave;  }  // export helper functions  getValue(ptr, type) {    type = type || 'i8';    if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit      switch(type) {        case 'i1': return this._HEAP8[((ptr)>>0)];        case 'i8': return this._HEAP8[((ptr)>>0)];        case 'i16': return this._HEAP16[((ptr)>>1)];        case 'i32': return this._HEAP32[((ptr)>>2)];        case 'i64': return this._HEAP32[((ptr)>>2)];        case 'float': return this._HEAPF32[((ptr)>>2)];        case 'double': return this._HEAPF64[((ptr)>>3)];        default: throw new Error('invalid type for getValue: ' + type);      }    return null;  }  writeArrayToMemory(array, buffer) {    this._HEAP8.set(array, buffer);  }}module.exports = CephesWrapper;
 |