UNPKG

@thi.ng/transducers

Version:

Collection of ~170 lightweight, composable transducers, reducers, generators, iterators for functional data transformations

80 lines (79 loc) 2.58 kB
import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; import { add } from "./add.js"; import { iterator1 } from "./iterator.js"; import { map } from "./map.js"; import { range } from "./range.js"; import { range2d } from "./range2d.js"; import { transduce } from "./transduce.js"; import { zip } from "./zip.js"; const buildKernel1d = (weights, w) => { const w2 = w >> 1; return [...zip(weights, range(-w2, w2 + 1))]; }; const buildKernel2d = (weights, w, h = w) => { const w2 = w >> 1; const h2 = h >> 1; return [...zip(weights, range2d(-w2, w2 + 1, -h2, h2 + 1))]; }; const __kernelLookup1d = (src, x, width, wrap, border) => wrap ? ({ 0: w, 1: ox }) => { const xx = x < -ox ? width + ox : x >= width - ox ? ox - 1 : x + ox; return w * src[xx]; } : ({ 0: w, 1: ox }) => { return x < -ox || x >= width - ox ? border : w * src[x + ox]; }; const __kernelLookup2d = (src, x, y, width, height, wrap, border) => wrap ? ({ 0: w, 1: { 0: ox, 1: oy } }) => { const xx = x < -ox ? width + ox : x >= width - ox ? ox - 1 : x + ox; const yy = y < -oy ? height + oy : y >= height - oy ? oy - 1 : y + oy; return w * src[yy * width + xx]; } : ({ 0: w, 1: { 0: ox, 1: oy } }) => { return x < -ox || y < -oy || x >= width - ox || y >= height - oy ? border : w * src[(y + oy) * width + x + ox]; }; const __kernelError = () => illegalArgs(`no kernel or kernel config`); function convolve1d(opts, indices) { if (indices) { return iterator1(convolve1d(opts), indices); } const { src, width } = opts; const wrap = opts.wrap !== false; const border = opts.border || 0; const rfn = opts.reduce || add; let kernel = opts.kernel; if (!kernel) { !(opts.weights && opts.kwidth) && __kernelError(); kernel = buildKernel1d(opts.weights, opts.kwidth); } return map( (p) => transduce( map(__kernelLookup1d(src, p, width, wrap, border)), rfn(), kernel ) ); } function convolve2d(opts, indices) { if (indices) { return iterator1(convolve2d(opts), indices); } const { src, width, height } = opts; const wrap = opts.wrap !== false; const border = opts.border || 0; const rfn = opts.reduce || add; let kernel = opts.kernel; if (!kernel) { !(opts.weights && opts.kwidth && opts.kheight) && __kernelError(); kernel = buildKernel2d(opts.weights, opts.kwidth, opts.kheight); } return map( (p) => transduce( map(__kernelLookup2d(src, p[0], p[1], width, height, wrap, border)), rfn(), kernel ) ); } export { buildKernel1d, buildKernel2d, convolve1d, convolve2d };