@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
JavaScript
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
};