Skip to content

Commit

Permalink
feat(vectors): add random vector ops for Vec2/3/4 & GVec
Browse files Browse the repository at this point in the history
- add randNorm*(), randMinMax*() & jitter*() fns
- add static randNorm() / randMinMax() methods in class wrappers
- add jitter() methods in class wrappers
- add op20/21(), op30/31(), op40/41()
- optimize opg*() fns (avoid multiplies)
- refactor swizzle2/3/4() to re-use setS2/3/4()
  • Loading branch information
postspectacular committed Sep 15, 2018
1 parent 7963e25 commit 4e23016
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 51 deletions.
65 changes: 55 additions & 10 deletions packages/vectors/src/gvec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,37 @@ import {
step1
} from "./math";

export const opg0 = (fn: () => number, a: Vec, num = a.length, i = 0, s = 1) => {
i += num * s;
while (i -= s, --num >= 0) {
a[i] = fn();
}
return a;
};

export const opg1 = (fn: (x: number) => number, a: Vec, num = a.length, i = 0, s = 1) => {
while (--num >= 0) {
a[i + num * s] = fn(a[i + num * s]);
i += num * s;
while (i -= s, --num >= 0) {
a[i] = fn(a[i]);
}
return a;
};

export const opg2 = (fn: (x: number, y: number) => number, a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => {
while (--num >= 0) {
a[ia + num * sa] = fn(a[ia + num * sa], b[ib + num * sb]);
ia += num * sa;
ib += num * sb;
while (ia -= sa, ib -= sb, --num >= 0) {
a[ia] = fn(a[ia], b[ib]);
}
return a;
};

export const opg3 = (fn: (x: number, y: number, z: number) => number, a: Vec, b: ReadonlyVec, c: ReadonlyVec, num = a.length, ia = 0, ib = 0, ic = 0, sa = 1, sb = 1, sc = 1) => {
while (--num >= 0) {
a[ia + num * sa] = fn(a[ia + num * sa], b[ib + num * sb], c[ic + num * sc]);
ia += num * sa;
ib += num * sb;
ic += num * sc;
while (ia -= sa, ib -= sb, ic -= sc, --num >= 0) {
a[ia] = fn(a[ia], b[ib], c[ic]);
}
return a;
};
Expand All @@ -43,19 +57,33 @@ export const get = (a: ReadonlyVec, num = a.length, i = 0, s = 1) =>
set(new (<any>(a.constructor))(num), a, num, 0, i, 1, s);

export const set = (a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => {
while (--num >= 0) {
a[ia + num * sa] = b[ib + num * sb];
ia += num * sa;
ib += num * sb;
while (ia -= sa, ib -= sb, --num >= 0) {
a[ia] = b[ib];
}
return a;
};

export const setN = (a: Vec, n: number, num = a.length, ia = 0, sa = 1) => {
while (--num >= 0) {
a[ia + num * sa] = n;
ia += num * sa;
while (ia -= sa, --num >= 0) {
a[ia] = n;
}
return a;
};

export const randNorm = (a: Vec, n = 1, num = a.length, ia = 0, sa = 1) =>
randMinMax(a, -n, n, num, ia, sa);

export const randMinMax = (a: Vec, min: number, max: number, num = a.length, ia = 0, sa = 1) => {
const d = max - min;
return opg0(() => min + d * Math.random(), a, num, ia, sa);
};

export const jitter = (a: Vec, n: number, num = a.length, ia = 0, sa = 1) =>
opg1((x) => x + Math.random() * 2 * n - n, a, num, ia, sa);

export const add = (a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) =>
opg2((x, y) => x + y, a, b, num, ia, ib, sa, sb);

Expand Down Expand Up @@ -199,6 +227,18 @@ export class GVec implements
return buf;
}

static of(size: number, n = 0) {
return new GVec(setN([], n, size));
}

static randNorm(size: number, n = 1) {
return new GVec(randNorm([], n, size));
}

static random(size: number, min: number, max: number) {
return new GVec(randMinMax([], min, max, size));
}

buf: Vec;
n: number;
i: number;
Expand Down Expand Up @@ -256,6 +296,11 @@ export class GVec implements
return this;
}

jitter(n = 1) {
jitter(this.buf, n, this.n, this.i, this.s);
return this;
}

add(v: Readonly<GVec>) {
this.ensureSize(v);
add(this.buf, v.buf, this.n, this.i, v.i, this.s, v.s);
Expand Down
60 changes: 42 additions & 18 deletions packages/vectors/src/vec2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
ILength
} from "@thi.ng/api/api";
import { isArrayLike } from "@thi.ng/checks/is-arraylike";

import {
IVec,
MAX4,
Expand All @@ -15,7 +14,7 @@ import {
Vec,
ZERO4
} from "./api";
import { declareIndices, $iter } from "./common";
import { $iter, declareIndices } from "./common";
import {
atan2Abs1,
EPS,
Expand All @@ -33,6 +32,18 @@ import {
export const op2 = (fn: (x: number) => number, a: Vec, ia = 0, sa = 1) =>
(a[ia] = fn(a[ia]), a[ia + sa] = fn(a[ia + sa]), a);

export const op20 = (fn: () => number, a: Vec, ia = 0, sa = 1) => (
a[ia] = fn(),
a[ia + sa] = fn(),
a
);

export const op21 = (fn: (a: number, n: number) => number, a: Vec, n: number, ia = 0, sa = 1) => (
a[ia] = fn(a[ia], n),
a[ia + sa] = fn(a[ia + sa], n),
a
);

export const op22 = (fn: (a: number, b: number) => number, a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => (
a[ia] = fn(a[ia], b[ib]),
a[ia + sa] = fn(a[ia + sa], b[ib + sb]),
Expand All @@ -51,14 +62,20 @@ export const setN2 = (a: Vec, n: number, ia = 0, sa = 1) =>
export const setS2 = (a: Vec, x: number, y: number, ia = 0, sa = 1) =>
(a[ia] = x, a[ia + sa] = y, a);

export const swizzle2 = (a: Vec, b: ReadonlyVec, x: number, y: number, ia = 0, ib = 0, sa = 1, sb = 1) => {
const xx = b[ib + x * sb];
const yy = b[ib + y * sb];
a[ia] = xx;
a[ia + sa] = yy;
return a;
export const randNorm2 = (a: Vec, n = 1, ia = 0, sa = 1) =>
randMinMax2(a, -n, n, ia, sa);

export const randMinMax2 = (a: Vec, min: number, max: number, ia = 0, sa = 1) => {
const d = max - min;
return op20(() => min + d * Math.random(), a, ia, sa);
};

export const jitter2 = (a: Vec, n: number, ia = 0, sa = 1) =>
op2((x) => x + Math.random() * 2 * n - n, a, ia, sa);

export const swizzle2 = (a: Vec, b: ReadonlyVec, x: number, y: number, ia = 0, ib = 0, sa = 1, sb = 1) =>
setS2(a, b[ib + x * sb], b[ib + y * sb], ia, sa);

export const swap2 = (a: Vec, b: Vec, ia = 0, ib = 0, sa = 1, sb = 1) => {
let t = a[ia]; a[ia] = b[ib]; b[ib] = t;
ia += sa; ib += sb;
Expand Down Expand Up @@ -149,17 +166,11 @@ export const cos2 = (a: Vec, ia = 0, sa = 1) =>
export const sqrt2 = (a: Vec, ia = 0, sa = 1) =>
op2(Math.sqrt, a, ia, sa);

export const pow2 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => (
a[ia] = Math.pow(a[ia], b[ib]),
a[ia + sa] = Math.pow(a[ia + sa], b[ib + sb]),
a
);
export const pow2 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) =>
op22(Math.pow, a, b, ia, ib, sa, sb);

export const powN2 = (a: Vec, n: number, ia = 0, sa = 1) => (
a[ia] = Math.pow(a[ia], n),
a[ia + sa] = Math.pow(a[ia + sa], n),
a
);
export const powN2 = (a: Vec, n: number, ia = 0, sa = 1) =>
op21(Math.pow, a, n, ia, sa);

export const madd2 = (a: Vec, b: ReadonlyVec, c: ReadonlyVec, ia = 0, ib = 0, ic = 0, sa = 1, sb = 1, sc = 1) =>
(a[ia] += b[ib] * c[ic], a[ia + sa] += b[ib + sb] * c[ic + sc], a);
Expand Down Expand Up @@ -399,6 +410,14 @@ export class Vec2 implements
);
}

static randNorm(n = 1) {
return new Vec2(randNorm2([], n));
}

static random(min: number, max: number) {
return new Vec2(randMinMax2([], min, max));
}

static add(a: Readonly<Vec2>, b: Readonly<Vec2>, out?: Vec2) {
!out && (out = new Vec2([]));
add2o(out.buf, a.buf, b.buf, out.i, a.i, b.i, out.s, a.s, b.s);
Expand Down Expand Up @@ -520,6 +539,11 @@ export class Vec2 implements
return this;
}

jitter(n = 1) {
jitter2(this.buf, n, this.i, this.s);
return this;
}

swizzle(v: IVec, x: number, y: number) {
swizzle2(this.buf, v.buf, x, y, this.i, v.i, this.s, v.s);
return this;
Expand Down
52 changes: 41 additions & 11 deletions packages/vectors/src/vec3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
ILength
} from "@thi.ng/api/api";
import { isArrayLike } from "@thi.ng/checks/is-arraylike";

import {
IVec,
MAX4,
Expand All @@ -15,7 +14,7 @@ import {
Vec,
ZERO4
} from "./api";
import { declareIndices, $iter } from "./common";
import { $iter, declareIndices } from "./common";
import {
atan2Abs1,
EPS,
Expand All @@ -42,6 +41,20 @@ export const op3 = (fn: (x: number) => number, a: Vec, ia = 0, sa = 1) => (
a
);

export const op30 = (fn: () => number, a: Vec, ia = 0, sa = 1) => (
a[ia] = fn(),
a[ia + sa] = fn(),
a[ia + 2 * sa] = fn(),
a
);

export const op31 = (fn: (a: number, n: number) => number, a: Vec, n: number, ia = 0, sa = 1) => (
a[ia] = fn(a[ia], n),
a[ia + sa] = fn(a[ia + sa], n),
a[ia + 2 * sa] = fn(a[ia + 2 * sa], n),
a
);

export const op32 = (fn: (a: number, b: number) => number, a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => (
a[ia] = fn(a[ia], b[ib]),
a[ia + sa] = fn(a[ia + sa], b[ib + sb]),
Expand Down Expand Up @@ -69,16 +82,20 @@ export const setN3 = (a: Vec, n: number, ia = 0, sa = 1) => (
export const setS3 = (a: Vec, x: number, y: number, z: number, ia = 0, sa = 1) =>
(a[ia] = x, a[ia + sa] = y, a[ia + 2 * sa] = z, a);

export const swizzle3 = (a: Vec, b: ReadonlyVec, x: number, y: number, z: number, ia = 0, ib = 0, sa = 1, sb = 1) => {
const xx = b[ib + x * sb];
const yy = b[ib + y * sb];
const zz = b[ib + z * sb];
a[ia] = xx;
a[ia + sa] = yy;
a[ia + 2 * sa] = zz;
return a;
export const randNorm3 = (a: Vec, n = 1, ia = 0, sa = 1) =>
randMinMax3(a, -n, n, ia, sa);

export const randMinMax3 = (a: Vec, min: number, max: number, ia = 0, sa = 1) => {
const d = max - min;
return op30(() => min + d * Math.random(), a, ia, sa);
};

export const jitter3 = (a: Vec, n: number, ia = 0, sa = 1) =>
op3((x) => x + Math.random() * 2 * n - n, a, ia, sa);

export const swizzle3 = (a: Vec, b: ReadonlyVec, x: number, y: number, z: number, ia = 0, ib = 0, sa = 1, sb = 1) =>
setS3(a, b[ib + x * sb], b[ib + y * sb], b[ib + z * sb], ia, sa);

export const swap3 = (a: Vec, b: Vec, ia = 0, ib = 0, sa = 1, sb = 1) => {
let t = a[ia]; a[ia] = b[ib]; b[ib] = t;
ia += sa; ib += sb;
Expand Down Expand Up @@ -225,7 +242,7 @@ export const pow3 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) =>
op32(Math.pow, a, b, ia, ib, sa, sb);

export const powN3 = (a: Vec, n: number, ia = 0, sa = 1) =>
op3((x) => Math.pow(x, n), a, ia, sa);
op31(Math.pow, a, n, ia, sa);

export const madd3 = (a: Vec, b: ReadonlyVec, c: ReadonlyVec, ia = 0, ib = 0, ic = 0, sa = 1, sb = 1, sc = 1) => (
a[ia] += b[ib] * c[ic],
Expand Down Expand Up @@ -534,6 +551,14 @@ export class Vec3 implements
return new Vec3(orthoNormal3(a.buf, b.buf, c.buf, a.i, b.i, c.i, a.s, b.s, c.s));
}

static randNorm(n = 1) {
return new Vec3(randNorm3([], n));
}

static random(min: number, max: number) {
return new Vec3(randMinMax3([], min, max));
}

static add(a: Readonly<Vec3>, b: Readonly<Vec3>, out?: Vec3) {
!out && (out = new Vec3([]));
add3o(out.buf, a.buf, b.buf, out.i, a.i, b.i, out.s, a.s, b.s);
Expand Down Expand Up @@ -656,6 +681,11 @@ export class Vec3 implements
return this;
}

jitter(n = 1) {
jitter3(this.buf, n, this.i, this.s);
return this;
}

swizzle(v: IVec, x: number, y: number, z: number) {
swizzle3(this.buf, v.buf, x, y, z, this.i, v.i, this.s, v.s);
return this;
Expand Down
Loading

0 comments on commit 4e23016

Please sign in to comment.