UNPKG

@thi.ng/vectors

Version:

Optimized 2d/3d/4d and arbitrary length vector operations, support for memory mapping/layouts

181 lines (180 loc) 5.04 kB
import { comp } from "@thi.ng/transducers/comp"; import { map } from "@thi.ng/transducers/map"; import { mapIndexed } from "@thi.ng/transducers/map-indexed"; import { range } from "@thi.ng/transducers/range"; import { str } from "@thi.ng/transducers/str"; import { take } from "@thi.ng/transducers/take"; import { transduce } from "@thi.ng/transducers/transduce"; import { zip } from "@thi.ng/transducers/zip"; import { vop } from "../vop.js"; import { ARGS_V, ARGS_VN, ARGS_VV, DEFAULT_OUT, FN, MATH, MATH_N, SARGS_VV, SIGNED, SIGNED_N, UNSIGNED, UNSIGNED_N } from "./templates.js"; const __lookup = (sym) => (i) => i > 1 ? `${sym}[i${sym}+${i}*s${sym}]` : i == 1 ? `${sym}[i${sym}+s${sym}]` : `${sym}[i${sym}]`; const __indicesStrided = (sym) => map(__lookup(sym), range()); const __indices = (sym) => map((i) => `${sym}[${i}]`, range()); const __assemble = (dim, tpl, syms, ret = "a", opJoin = "", pre = "", post = "", strided = false) => [ pre, transduce( comp( take(dim), mapIndexed((i, x) => tpl(x, i)) ), str(opJoin), zip.apply( null, syms.split(",").map(strided ? __indicesStrided : __indices) ) ), post, ret !== "" ? `return ${ret};` : "" ]; const __assembleG = (tpl, syms, ret = "a", pre, post, strided = false) => [ pre, "for(let i=a.length;--i>=0;) {", tpl( syms.split(",").map(strided ? (x) => `${x}[i${x}+i*s${x}]` : (x) => `${x}[i]`) ), "}", post, ret !== null ? `return ${ret};` : "" ]; const __assembleS = (tpl, syms = ARGS_VV, ret = "o", pre = DEFAULT_OUT, post) => [ pre, "while(k-->0) {", tpl(syms.split(",").map((x) => `${x}[i${x}+k*s${x}]`)), "}", post, ret !== null ? `return ${ret};` : "" ]; const __defaultOut = (o, args) => `!${o} && (${o}=${args.split(",")[1]});`; const compile = (dim, tpl, args, syms = args, ret = "a", opJoin, pre, post, strided = false) => new Function( args, __assemble(dim, tpl, syms, ret, opJoin, pre, post, strided).join("") ); const compileHOF = (dim, fns, tpl, hofArgs, args, syms = args, ret = "a", opJoin = "", pre, post, strided = false) => { return new Function( hofArgs, `return (${args})=>{${__assemble( dim, tpl, syms, ret, opJoin, pre, post, strided ).join("")}}` )(...fns); }; const compileG = (tpl, args, syms = args, ret = "a", pre, post, strided = false) => new Function( args, __assembleG(tpl, syms, ret, pre, post, strided).join("") ); const compileS = (tpl, args, syms = args, ret, pre, post) => new Function(args, __assembleS(tpl, syms, ret, pre, post).join("")); const compileGHOF = (fns, tpl, hofArgs, args, syms = args, ret = "a", pre, post, strided = false) => new Function( hofArgs, `return (${args})=>{${__assembleG( tpl, syms, ret, pre, post, strided ).join("")}}` )(...fns); const defOp = (tpl, args = ARGS_VV, syms, ret = "o", dispatch = 1, pre) => { syms = syms || args; pre = pre != null ? pre : __defaultOut(ret, syms); const fn = vop(dispatch); const $ = (dim) => fn.add(dim, compile(dim, tpl, args, syms, ret, "", pre)); fn.default(compileG(tpl, args, syms, ret, pre)); return [fn, $(2), $(3), $(4)]; }; const defFnOp = (op) => defOp(FN(op), ARGS_V); const defHofOp = (op, tpl, args = ARGS_V, syms, ret = "o", dispatch = 1, pre) => { const _tpl = tpl || FN("op"); syms = syms || args; pre = pre != null ? pre : __defaultOut(ret, syms); const fn = vop(dispatch); const $ = (dim) => fn.add( dim, compileHOF(dim, [op], _tpl, "op", args, syms, ret, "", pre) ); fn.default(compileGHOF([op], _tpl, "op", args, syms, ret, pre)); return [fn, $(2), $(3), $(4)]; }; const defOpS = (tpl, args = ARGS_VV, idxArgs = SARGS_VV, syms = ARGS_VV, ret = "o", pre, sizes = [2, 3, 4]) => [ compileS(tpl, `${args},k,${idxArgs}`, syms, ret, pre), ...sizes.map( (dim) => compile( dim, tpl, `${args},${idxArgs}`, syms, ret, "", pre != null ? pre : __defaultOut(ret, syms), "", true ) ) ]; const defHofOpS = (op, tpl, args = ARGS_VV, idxArgs = SARGS_VV, syms = ARGS_VV, ret = "o", pre, sizes = [2, 3, 4]) => [ new Function( "op", `return (${args},k,${idxArgs})=>{${__assembleS( tpl, syms, ret, pre ).join("")}}` )(op), ...sizes.map( (dim) => compileHOF( dim, [op], tpl, "op", `${args},${idxArgs}`, syms, ret, "", pre != null ? pre : __defaultOut(ret, syms), "", true ) ) ]; const defMathOp = (op) => defOp(MATH(op)); const defMathOpN = (op) => defOp(MATH_N(op), ARGS_VN); const defBitOp = (op, signed = false) => defOp((signed ? SIGNED : UNSIGNED)(op)); const defBitOpN = (op, signed = false) => defOp((signed ? SIGNED_N : UNSIGNED_N)(op), ARGS_VN); export { __defaultOut, compile, compileG, compileGHOF, compileHOF, compileS, defBitOp, defBitOpN, defFnOp, defHofOp, defHofOpS, defMathOp, defMathOpN, defOp, defOpS };