import { readFileSync, existsSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const wasmCache = new Map();
export async function loadTemporalNeuralSolver() {
if (wasmCache.has('temporal_neural')) {
return wasmCache.get('temporal_neural');
}
try {
const wasmPath = join(__dirname, '..', 'wasm', 'temporal_neural_solver_bg.wasm');
if (!existsSync(wasmPath)) {
console.warn(`WASM file not found at ${wasmPath}`);
return null;
}
const wasmBuffer = readFileSync(wasmPath);
const imports = {
wbg: {
__wbg_random_e6e0a85ff4db8ab6: () => Math.random(),
__wbindgen_throw: (ptr, len) => {
throw new Error(`WASM error at ${ptr}, len ${len}`);
}
}
};
const { instance } = await globalThis.WebAssembly.instantiate(wasmBuffer, imports);
const solver = {
memory: instance.exports.memory,
multiplyMatrixVector: (matrix, vector, rows, cols) => {
if (!instance.exports.__wbindgen_malloc) {
return multiplyMatrixVectorJS(matrix, vector, rows, cols);
}
const matrixPtr = instance.exports.__wbindgen_malloc(matrix.byteLength, 8);
const vectorPtr = instance.exports.__wbindgen_malloc(vector.byteLength, 8);
const resultPtr = instance.exports.__wbindgen_malloc(rows * 8, 8);
const memory = new Float64Array(instance.exports.memory.buffer);
memory.set(matrix, matrixPtr / 8);
memory.set(vector, vectorPtr / 8);
if (instance.exports.matrix_multiply_vector) {
instance.exports.matrix_multiply_vector(matrixPtr, vectorPtr, resultPtr, rows, cols);
}
else {
for (let i = 0; i < rows; i++) {
let sum = 0;
for (let j = 0; j < cols; j++) {
sum += memory[matrixPtr / 8 + i * cols + j] * memory[vectorPtr / 8 + j];
}
memory[resultPtr / 8 + i] = sum;
}
}
const result = new Float64Array(rows);
result.set(memory.slice(resultPtr / 8, resultPtr / 8 + rows));
if (instance.exports.__wbindgen_free) {
instance.exports.__wbindgen_free(matrixPtr, matrix.byteLength, 8);
instance.exports.__wbindgen_free(vectorPtr, vector.byteLength, 8);
instance.exports.__wbindgen_free(resultPtr, rows * 8, 8);
}
return result;
},
getMemoryUsage: () => {
return instance.exports.memory.buffer.byteLength;
}
};
wasmCache.set('temporal_neural', solver);
return solver;
}
catch (error) {
console.warn('Failed to load temporal neural WASM, using JS fallback');
return null;
}
}
export async function loadGraphReasonerWasm() {
if (wasmCache.has('graph_reasoner')) {
return wasmCache.get('graph_reasoner');
}
try {
const wasmPath = join(__dirname, '..', 'wasm', 'graph_reasoner_bg.wasm');
const wasmBuffer = readFileSync(wasmPath);
const imports = {
wbg: {
__wbindgen_object_drop_ref: () => { },
__wbindgen_string_new: (ptr, len) => ptr,
__wbindgen_throw: (ptr, len) => {
throw new Error(`WASM error at ${ptr}`);
},
__wbg_random_e6e0a85ff4db8ab6: () => Math.random(),
__wbg_now_3141b3797eb98e0b: () => Date.now()
}
};
const { instance } = await globalThis.WebAssembly.instantiate(wasmBuffer, imports);
const reasoner = {
memory: instance.exports.memory,
computePageRank: (adjacency, n, damping = 0.85, iterations = 100) => {
if (instance.exports.pagerank_compute) {
const adjPtr = instance.exports.__wbindgen_malloc(adjacency.byteLength, 8);
const resultPtr = instance.exports.__wbindgen_malloc(n * 8, 8);
const memory = new Float64Array(instance.exports.memory.buffer);
memory.set(adjacency, adjPtr / 8);
instance.exports.pagerank_compute(adjPtr, resultPtr, n, damping, iterations);
const result = new Float64Array(n);
result.set(memory.slice(resultPtr / 8, resultPtr / 8 + n));
instance.exports.__wbindgen_free(adjPtr, adjacency.byteLength, 8);
instance.exports.__wbindgen_free(resultPtr, n * 8, 8);
return result;
}
return computePageRankJS(adjacency, n, damping, iterations);
}
};
wasmCache.set('graph_reasoner', reasoner);
return reasoner;
}
catch (error) {
console.warn('Failed to load graph reasoner WASM, using JS fallback');
return null;
}
}
export async function initializeAllWasm() {
const [temporal, graph] = await Promise.all([
loadTemporalNeuralSolver(),
loadGraphReasonerWasm()
]);
const hasWasm = !!(temporal || graph);
if (hasWasm) {
console.log('✅ WASM acceleration enabled');
if (temporal)
console.log(' - Temporal Neural Solver');
if (graph)
console.log(' - Graph Reasoner');
}
else {
console.log('⚠️ Running in pure JavaScript mode');
}
return { temporal, graph, hasWasm };
}
function multiplyMatrixVectorJS(matrix, vector, rows, cols) {
const result = new Float64Array(rows);
for (let i = 0; i < rows; i++) {
let sum = 0;
for (let j = 0; j < cols; j++) {
sum += matrix[i * cols + j] * vector[j];
}
result[i] = sum;
}
return result;
}
function computePageRankJS(adjacency, n, damping, iterations) {
const rank = new Float64Array(n);
const newRank = new Float64Array(n);
for (let i = 0; i < n; i++) {
rank[i] = 1.0 / n;
}
for (let iter = 0; iter < iterations; iter++) {
for (let i = 0; i < n; i++) {
newRank[i] = (1 - damping) / n;
for (let j = 0; j < n; j++) {
if (adjacency[j * n + i] > 0) {
let outDegree = 0;
for (let k = 0; k < n; k++) {
if (adjacency[j * n + k] > 0)
outDegree++;
}
if (outDegree > 0) {
newRank[i] += damping * rank[j] / outDegree;
}
}
}
}
rank.set(newRank);
}
return rank;
}
export { multiplyMatrixVectorJS, computePageRankJS };