From b5ed2545add8f8a9d3cc50b9dcad3387aae95872 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 28 Sep 2018 04:57:05 +0100 Subject: [PATCH] feat(vectors): add vector ops codegen, update basic vec2/3/4 ops (#51) --- packages/vectors/src/api.ts | 12 +++ packages/vectors/src/codegen.ts | 70 +++++++++++++++++ packages/vectors/src/index.ts | 2 + packages/vectors/src/vec2.ts | 72 ++++++----------- packages/vectors/src/vec3.ts | 120 ++++++----------------------- packages/vectors/src/vec4.ts | 132 ++++++-------------------------- 6 files changed, 159 insertions(+), 249 deletions(-) create mode 100644 packages/vectors/src/codegen.ts diff --git a/packages/vectors/src/api.ts b/packages/vectors/src/api.ts index 1cb3389c74..46bd1d088f 100644 --- a/packages/vectors/src/api.ts +++ b/packages/vectors/src/api.ts @@ -18,12 +18,24 @@ export type VecOp1 = (v: Vec, i?: number, s?: number) => T; */ export type VecOp2 = (a: Vec, b: ReadonlyVec, ia?: number, ib?: number, sa?: number, sb?: number) => T; +/** + * A vector operation involving a vector and a scalar. The vector might + * be modified. + */ +export type VecOpN2 = (a: Vec, n: number, ia?: number, sa?: number) => T; + /** * A vector operation involving input readonly two vectors and writing * result to an output vector `out`. */ export type VecOp2o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io?: number, ia?: number, ib?: number, so?: number, sa?: number, sb?: number) => T; +/** + * A vector operation involving input readonly two vectors and writing + * result to an output vector `out`. + */ +export type VecOpN2o = (out: Vec, a: ReadonlyVec, n: number, io?: number, ia?: number, so?: number, sa?: number) => T; + /** * A readonly vector operation involving only a single vector. */ diff --git a/packages/vectors/src/codegen.ts b/packages/vectors/src/codegen.ts new file mode 100644 index 0000000000..38329833dc --- /dev/null +++ b/packages/vectors/src/codegen.ts @@ -0,0 +1,70 @@ +import { + Vec, + VecOp1, + VecOp2, + VecOp2o, + VecOpN2, + VecOpN2o +} from "@thi.ng/vectors/src/api"; + +const compile = (args: string, src: string[]) => + new Function(args, src.join("")); + +const assemble = (fn: (op: string, i: number) => string, dim: number, op: string, ret = "a") => { + const src = []; + for (let i = 0; i < dim; i++) { + src.push(fn(op, i)); + } + src.push(`return ${ret};`); + return src; +} + +const uniop = (op: string, i: number) => + i > 1 ? + `a[ia+${i}*sa]=${op}(a[ia+${i}*sa]);` : + i == 1 ? + `a[ia+sa]=${op}(a[ia+sa]);` : + `a[ia]=${op}(a[ia]);`; + +const binop = (op: string, i: number) => + i > 1 ? + `a[ia+${i}*sa]${op}=b[ib+${i}*sb];` : + i == 1 ? + `a[ia+sa]${op}=b[ib+sb];` : + `a[ia]${op}=b[ib];`; + +const binopN = (op: string, i: number) => + i > 1 ? + `a[ia+${i}*sa]${op}=n;` : + i == 1 ? + `a[ia+sa]${op}=n;` : + `a[ia]${op}=n;`; + +const binopO = (op: string, i: number) => + i > 1 ? + `o[io+${i}*so]=a[ia+${i}*sa]${op}b[ib+${i}*sb];` : + i == 1 ? + `o[io+so]=a[ia+sa]${op}b[ib+sb];` : + `o[io]=a[ia]${op}b[ib];`; + +const binopON = (op: string, i: number) => + i > 1 ? + `o[io+${i}*so]=a[ia+${i}*sa]${op}n;` : + i == 1 ? + `o[io+so]=a[ia+sa]${op}n;` : + `o[io]=a[ia]${op}n;`; + +export const vuniop = (dim: number, op: string): VecOp1 => + compile("a,ia=0,sa=1", assemble(uniop, dim, op)); + +export const vbinop = (dim: number, op: string): VecOp2 => + compile("a,b,ia=0,ib=0,sa=1,sb=1", assemble(binop, dim, op)); + +export const vbinopN = (dim: number, op: string): VecOpN2 => + compile("a,n,ia=0,sa=1", assemble(binopN, dim, op)); + +export const vbinopO = (dim: number, op: string): VecOp2o => + compile("o,a,b,io=0,ia=0,ib=0,so=1,sa=1,sb=1", assemble(binopO, dim, op, "o")); + +export const vbinopON = (dim: number, op: string): VecOpN2o => + compile("o,a,n,io=0,ia=0,so=1,sa=1", assemble(binopON, dim, op, "o")); diff --git a/packages/vectors/src/index.ts b/packages/vectors/src/index.ts index 5ffd20465f..f795cc3571 100644 --- a/packages/vectors/src/index.ts +++ b/packages/vectors/src/index.ts @@ -8,3 +8,5 @@ export * from "./gvec"; export * from "./vec2"; export * from "./vec3"; export * from "./vec4"; + +export * from "./codegen"; diff --git a/packages/vectors/src/vec2.ts b/packages/vectors/src/vec2.ts index 98fdad7ef8..ad46db0484 100644 --- a/packages/vectors/src/vec2.ts +++ b/packages/vectors/src/vec2.ts @@ -14,6 +14,12 @@ import { Vec, ZERO4 } from "./api"; +import { + vbinop, + vbinopN, + vbinopO, + vbinopON +} from "./codegen"; import { $iter, declareIndices } from "./common"; import { atan2Abs1, @@ -91,53 +97,25 @@ export const eqDelta2 = (a: ReadonlyVec, b: ReadonlyVec, eps = EPS, ia = 0, ib = eqDelta1(a[ia], b[ib], eps) && eqDelta1(a[ia + sa], b[ib + sb], eps); -export const add2 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - (a[ia] += b[ib], a[ia + sa] += b[ib + sb], a); - -export const sub2 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - (a[ia] -= b[ib], a[ia + sa] -= b[ib + sb], a); - -export const mul2 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - (a[ia] *= b[ib], a[ia + sa] *= b[ib + sb], a); - -export const div2 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - (a[ia] /= b[ib], a[ia + sa] /= b[ib + sb], a); - -export const add2o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io = 0, ia = 0, ib = 0, so = 1, sa = 1, sb = 1) => - (out[io] = a[ia] + b[ib], out[io + so] = a[ia + sa] + b[ib + sb], out); - -export const sub2o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io = 0, ia = 0, ib = 0, so = 1, sa = 1, sb = 1) => - (out[io] = a[ia] - b[ib], out[io + so] = a[ia + sa] - b[ib + sb], out); - -export const mul2o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io = 0, ia = 0, ib = 0, so = 1, sa = 1, sb = 1) => - (out[io] = a[ia] * b[ib], out[io + so] = a[ia + sa] * b[ib + sb], out); - -export const div2o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io = 0, ia = 0, ib = 0, so = 1, sa = 1, sb = 1) => - (out[io] = a[ia] / b[ib], out[io + so] = a[ia + sa] / b[ib + sb], out); - -export const addN2 = (a: Vec, n: number, ia = 0, sa = 1) => - (a[ia] += n, a[ia + sa] += n, a); - -export const subN2 = (a: Vec, n: number, ia = 0, sa = 1) => - (a[ia] -= n, a[ia + sa] -= n, a); - -export const mulN2 = (a: Vec, n: number, ia = 0, sa = 1) => - (a[ia] *= n, a[ia + sa] *= n, a); - -export const divN2 = (a: Vec, n: number, ia = 0, sa = 1) => - (a[ia] /= n, a[ia + sa] /= n, a); - -export const addN2o = (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => - (out[io] = a[ia] + n, out[io + so] = a[ia + sa] + n, out); - -export const subN2o = (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => - (out[io] = a[ia] - n, out[io + so] = a[ia + sa] - n, out); - -export const mulN2o = (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => - (out[io] = a[ia] * n, out[io + so] = a[ia + sa] * n, out); - -export const divN2o = (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => - (out[io] = a[ia] / n, out[io + so] = a[ia + sa] / n, out); +export const add2 = vbinop(2, "+"); +export const sub2 = vbinop(2, "-"); +export const mul2 = vbinop(2, "*"); +export const div2 = vbinop(2, "/"); + +export const add2o = vbinopO(2, "+"); +export const sub2o = vbinopO(2, "-"); +export const mul2o = vbinopO(2, "*"); +export const div2o = vbinopO(2, "/"); + +export const addN2 = vbinopN(2, "+"); +export const subN2 = vbinopN(2, "-"); +export const mulN2 = vbinopN(2, "*"); +export const divN2 = vbinopN(2, "/"); + +export const addN2o = vbinopON(2, "+"); +export const subN2o = vbinopON(2, "-"); +export const mulN2o = vbinopON(2, "*"); +export const divN2o = vbinopON(2, "/"); export const neg2 = (a: Vec, ia = 0, sa = 1) => mulN2(a, -1, ia, sa); diff --git a/packages/vectors/src/vec3.ts b/packages/vectors/src/vec3.ts index 91ad0dc891..3623be771f 100644 --- a/packages/vectors/src/vec3.ts +++ b/packages/vectors/src/vec3.ts @@ -14,6 +14,12 @@ import { Vec, ZERO4 } from "./api"; +import { + vbinop, + vbinopN, + vbinopO, + vbinopON +} from "./codegen"; import { $iter, declareIndices } from "./common"; import { atan2Abs1, @@ -115,101 +121,25 @@ export const eqDelta3 = (a: ReadonlyVec, b: ReadonlyVec, eps = EPS, ia = 0, ib = eqDelta1(a[ia + sa], b[ib + sb], eps) && eqDelta1(a[ia + 2 * sa], b[ib + 2 * sb], eps); -export const add3 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => ( - a[ia] += b[ib], - a[ia + sa] += b[ib + sb], - a[ia + 2 * sa] += b[ib + 2 * sb], - a -); - -export const mul3 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => ( - a[ia] *= b[ib], - a[ia + sa] *= b[ib + sb], - a[ia + 2 * sa] *= b[ib + 2 * sb], - a -); - -export const sub3 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => ( - a[ia] -= b[ib], - a[ia + sa] -= b[ib + sb], - a[ia + 2 * sa] -= b[ib + 2 * sb], - a -); - -export const div3 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => ( - a[ia] /= b[ib], - a[ia + sa] /= b[ib + sb], - a[ia + 2 * sa] /= b[ib + 2 * sb], - a -); - -export const add3o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io = 0, ia = 0, ib = 0, so = 1, sa = 1, sb = 1) => ( - out[io] = a[ia] + b[ib], - out[io + so] = a[ia + sa] + b[ib + sb], - out[io + 2 * so] = a[ia + 2 * sa] + b[ib + 2 * sb], - out -); - -export const sub3o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io = 0, ia = 0, ib = 0, so = 1, sa = 1, sb = 1) => ( - out[io] = a[ia] - b[ib], - out[io + so] = a[ia + sa] - b[ib + sb], - out[io + 2 * so] = a[ia + 2 * sa] - b[ib + 2 * sb], - out -); - -export const mul3o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io = 0, ia = 0, ib = 0, so = 1, sa = 1, sb = 1) => ( - out[io] = a[ia] * b[ib], - out[io + so] = a[ia + sa] * b[ib + sb], - out[io + 2 * so] = a[ia + 2 * sa] * b[ib + 2 * sb], - out -); - -export const div3o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io = 0, ia = 0, ib = 0, so = 1, sa = 1, sb = 1) => ( - out[io] = a[ia] / b[ib], - out[io + so] = a[ia + sa] / b[ib + sb], - out[io + 2 * so] = a[ia + 2 * sa] / b[ib + 2 * sb], - out -); - -export const addN3 = (a: Vec, n: number, ia = 0, sa = 1) => - (a[ia] += n, a[ia + sa] += n, a[ia + 2 * sa] += n, a); - -export const subN3 = (a: Vec, n: number, ia = 0, sa = 1) => - (a[ia] -= n, a[ia + sa] -= n, a[ia + 2 * sa] -= n, a); - -export const mulN3 = (a: Vec, n: number, ia = 0, sa = 1) => - (a[ia] *= n, a[ia + sa] *= n, a[ia + 2 * sa] *= n, a); - -export const divN3 = (a: Vec, n: number, ia = 0, sa = 1) => - (a[ia] /= n, a[ia + sa] /= n, a[ia + 2 * sa] /= n, a); - -export const addN3o = (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => ( - out[io] = a[ia] + n, - out[io + so] = a[ia + sa] + n, - out[io + 2 * so] = a[ia + 2 * sa] + n, - out -); - -export const subN3o = (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => ( - out[io] = a[ia] - n, - out[io + so] = a[ia + sa] - n, - out[io + 2 * so] = a[ia + 2 * sa] - n, - out -); - -export const mulN3o = (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => ( - out[io] = a[ia] * n, - out[io + so] = a[ia + sa] * n, - out[io + 2 * so] = a[ia + 2 * sa] * n, - out -); - -export const divN3o = (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => ( - out[io] = a[ia] / n, - out[io + so] = a[ia + sa] / n, - out[io + 2 * so] = a[ia + 2 * sa] / n, - out -); +export const add3 = vbinop(3, "+"); +export const sub3 = vbinop(3, "-"); +export const mul3 = vbinop(3, "*"); +export const div3 = vbinop(3, "/"); + +export const add3o = vbinopO(3, "+"); +export const sub3o = vbinopO(3, "-"); +export const mul3o = vbinopO(3, "*"); +export const div3o = vbinopO(3, "/"); + +export const addN3 = vbinopN(3, "+"); +export const subN3 = vbinopN(3, "-"); +export const mulN3 = vbinopN(3, "*"); +export const divN3 = vbinopN(3, "/"); + +export const addN3o = vbinopON(3, "+"); +export const subN3o = vbinopON(3, "-"); +export const mulN3o = vbinopON(3, "*"); +export const divN3o = vbinopON(3, "/"); export const neg3 = (a: Vec, ia = 0, sa = 1) => mulN3(a, -1, ia, sa); diff --git a/packages/vectors/src/vec4.ts b/packages/vectors/src/vec4.ts index 7e775b157a..34d5ed6f82 100644 --- a/packages/vectors/src/vec4.ts +++ b/packages/vectors/src/vec4.ts @@ -14,6 +14,12 @@ import { Vec, ZERO4 } from "./api"; +import { + vbinop, + vbinopN, + vbinopO, + vbinopON +} from "./codegen"; import { $iter, declareIndices } from "./common"; import { EPS, @@ -122,113 +128,25 @@ export const eqDelta4 = (a: ReadonlyVec, b: ReadonlyVec, eps = EPS, ia = 0, ib = eqDelta1(a[ia + 2 * sa], b[ib + 2 * sb], eps) && eqDelta1(a[ia + 3 * sa], b[ib + 3 * sb], eps); -export const add4 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => ( - a[ia] += b[ib], - a[ia + sa] += b[ib + sb], - a[ia + 2 * sa] += b[ib + 2 * sb], - a[ia + 3 * sa] += b[ib + 3 * sb], - a -); - -export const mul4 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => ( - a[ia] *= b[ib], - a[ia + sa] *= b[ib + sb], - a[ia + 2 * sa] *= b[ib + 2 * sb], - a[ia + 3 * sa] *= b[ib + 3 * sb], - a -); - -export const sub4 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => ( - a[ia] -= b[ib], - a[ia + sa] -= b[ib + sb], - a[ia + 2 * sa] -= b[ib + 2 * sb], - a[ia + 3 * sa] -= b[ib + 3 * sb], - a -); - -export const div4 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => ( - a[ia] /= b[ib], - a[ia + sa] /= b[ib + sb], - a[ia + 2 * sa] /= b[ib + 2 * sb], - a[ia + 3 * sa] /= b[ib + 3 * sb], - a -); - -export const add4o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io = 0, ia = 0, ib = 0, so = 1, sa = 1, sb = 1) => ( - out[io] = a[ia] + b[ib], - out[io + so] = a[ia + sa] + b[ib + sb], - out[io + 2 * so] = a[ia + 2 * sa] + b[ib + 2 * sb], - out[io + 3 * so] = a[ia + 3 * sa] + b[ib + 3 * sb], - out -); - -export const sub4o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io = 0, ia = 0, ib = 0, so = 1, sa = 1, sb = 1) => ( - out[io] = a[ia] - b[ib], - out[io + so] = a[ia + sa] - b[ib + sb], - out[io + 2 * so] = a[ia + 2 * sa] - b[ib + 2 * sb], - out[io + 3 * so] = a[ia + 3 * sa] - b[ib + 3 * sb], - out -); - -export const mul4o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io = 0, ia = 0, ib = 0, so = 1, sa = 1, sb = 1) => ( - out[io] = a[ia] * b[ib], - out[io + so] = a[ia + sa] * b[ib + sb], - out[io + 2 * so] = a[ia + 2 * sa] * b[ib + 2 * sb], - out[io + 3 * so] = a[ia + 3 * sa] * b[ib + 3 * sb], - out -); - -export const div4o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io = 0, ia = 0, ib = 0, so = 1, sa = 1, sb = 1) => ( - out[io] = a[ia] / b[ib], - out[io + so] = a[ia + sa] / b[ib + sb], - out[io + 2 * so] = a[ia + 2 * sa] / b[ib + 2 * sb], - out[io + 3 * so] = a[ia + 3 * sa] / b[ib + 3 * sb], - out -); - -export const addN4 = (a: Vec, n: number, ia = 0, sa = 1) => - (a[ia] += n, a[ia + sa] += n, a[ia + 2 * sa] += n, a[ia + 3 * sa] += n, a); - -export const subN4 = (a: Vec, n: number, ia = 0, sa = 1) => - (a[ia] -= n, a[ia + sa] -= n, a[ia + 2 * sa] -= n, a[ia + 3 * sa] -= n, a); - -export const mulN4 = (a: Vec, n: number, ia = 0, sa = 1) => - (a[ia] *= n, a[ia + sa] *= n, a[ia + 2 * sa] *= n, a[ia + 3 * sa] *= n, a); - -export const divN4 = (a: Vec, n: number, ia = 0, sa = 1) => - (a[ia] /= n, a[ia + sa] /= n, a[ia + 2 * sa] /= n, a[ia + 3 * sa] /= n, a); - -export const addN4o = (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => ( - out[io] = a[ia] + n, - out[io + so] = a[ia + sa] + n, - out[io + 2 * so] = a[ia + 2 * sa] + n, - out[io + 3 * so] = a[ia + 3 * sa] + n, - out -); - -export const subN4o = (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => ( - out[io] = a[ia] - n, - out[io + so] = a[ia + sa] - n, - out[io + 2 * so] = a[ia + 2 * sa] - n, - out[io + 3 * so] = a[ia + 3 * sa] - n, - out -); - -export const mulN4o = (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => ( - out[io] = a[ia] * n, - out[io + so] = a[ia + sa] * n, - out[io + 2 * so] = a[ia + 2 * sa] * n, - out[io + 3 * so] = a[ia + 3 * sa] * n, - out -); - -export const divN4o = (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => ( - out[io] = a[ia] / n, - out[io + so] = a[ia + sa] / n, - out[io + 2 * so] = a[ia + 2 * sa] / n, - out[io + 3 * so] = a[ia + 3 * sa] / n, - out -); +export const add4 = vbinop(4, "+"); +export const sub4 = vbinop(4, "-"); +export const mul4 = vbinop(4, "*"); +export const div4 = vbinop(4, "/"); + +export const add4o = vbinopO(4, "+"); +export const sub4o = vbinopO(4, "-"); +export const mul4o = vbinopO(4, "*"); +export const div4o = vbinopO(4, "/"); + +export const addN4 = vbinopN(4, "+"); +export const subN4 = vbinopN(4, "-"); +export const mulN4 = vbinopN(4, "*"); +export const divN4 = vbinopN(4, "/"); + +export const addN4o = vbinopON(4, "+"); +export const subN4o = vbinopON(4, "-"); +export const mulN4o = vbinopON(4, "*"); +export const divN4o = vbinopON(4, "/"); export const neg4 = (a: Vec, ia = 0, sa = 1) => mulN4(a, -1, ia, sa);