Options
All
  • Public
  • Public/Protected
  • All
Menu

@thi.ng/vectors

vectors

npm versionnpm downloads Twitter Follow

This project is part of the @thi.ng/umbrella monorepo.

About

Optimized 2d/3d/4d and arbitrary length vector operations.

Likely the most comprehensive vector library for TypeScript / JavaScript currently available.

This package provides ~720 largely code generated functions and supporting types to perform vector operations on fixed and arbitrary-length vectors, both packed and strided (i.e. where individual vector components are not successive array elements, for example in SOA memory layouts).

Includes componentwise logic operations for boolean vectors, componentwise comparisons for numeric vectors and componentwise binary ops for signed & unsigned integer vectors.

Features

  • Small & fast: The vast majority of functions are code generated with fixed-sized versions not using any loops. Minified + gzipped, the entire package is ~10.1KB (though you'll hardly ever use all functions).
  • Unified API: Any ArrayLike type can be used as vector containers (e.g. JS arrays, typed arrays, custom impls). Most functions are implemented as multi-methods, dispatching to any potentially optimized versions based on given vector arguments.
  • Highly modular: Each function is defined in its own submodule / file. In addition to each generic multi-method base function, all fixed-length optimized versions are exported too. E.g. If add performs vector addition on arbitrary-length vectors, add2, add3, add4 are the optimized version for fixed-length vectors...
  • Extensible: Custom vector ops can be defined in a similar manner using the provided code generation helpers (see vop.ts and codegen.ts for details).
  • Immutable by default: Each operation producing a vector result takes an output vector as first argument. If null, the vector given as 2nd argument will be used as output (i.e. for mutation).
  • Strided vector support is handled via the lightweight Vec2/3/4 class wrappers and the gvec() proxy (for generic, arbitrary-length vectors). These types behave like normal arrays (for read/write operations) and are also iterable. A subset of functions (suffixed with S, e.g. addS vs. add) also support striding without the need for extra class wrappers. This is handled via additional index and stride arguments for each input/output vector. These functions are only available for sizes 2 / 3 / 4, though.
  • Random vector functions support the IRandom interface defined by @thi.ng/random to work with custom (P)RNGs. If omitted, the built-in Math.random() will be used.

Partially ported from thi.ng/geom (Clojure) and c.thi.ng (C11).

Status

STABLE - used in production

Breaking changes in v3.0.0

  • to avoid confusion, the arg order of madd and maddN functions have been updated to be compatible with the OpenCL mad function and to generally follow the expanded name, i.e. multiply-add:
    • madd([], a, b, c): before a + b * c, now: a * b + c
    • maddN([], a, b, n) => maddN([], a, n, b) (i.e. a * n + b)
  • rename perpendicularLeft2 => perpendicularCCW
  • rename perpendicularRight2 => perpendicularCW
  • rename normalLeft2/ normalRight2 => normalCCW / normalCW

Related packages

Installation

yarn add @thi.ng/vectors
// ES module
<script type="module" src="https://unpkg.com/@thi.ng/vectors?module" crossorigin></script>

// UMD
<script src="https://unpkg.com/@thi.ng/vectors/lib/index.umd.js" crossorigin></script>

Package sizes (gzipped, pre-treeshake): ESM: 11.14 KB / CJS: 14.02 KB / UMD: 12.34 KB

Dependencies

Usage examples

Several demos in this repo's /examples directory are using this package.

A selection:

ScreenshotDescriptionLive demoSource
Canvas based dial widgetDemoSource
Doodle w/ K-nearest neighbor search result visualizationDemoSource
Mouse gesture / stroke analysis, simplification, corner detectionDemoSource
Realtime analog clock demoDemoSource
Interactive pattern drawing demo using transducersDemoSource
2D Bezier curve-guided particle systemDemoSource
Various hdom-canvas shape drawing examples & SVG conversion / exportDemoSource
Animated sine plasma effect visualized using contour linesDemoSource
CLI util to visualize umbrella pkg statsDemoSource
Animated Voronoi diagram, cubic splines & SVG downloadDemoSource
2D scenegraph & shape pickingDemoSource
2D scenegraph & image map based geometry manipulationDemoSource
Entity Component System w/ 100k 3D particlesDemoSource
3D wireframe textmode demoDemoSource
WebGL multi-colored cube meshDemoSource
WebGL instancing, animated gridDemoSource
WebGL MSDF text rendering & particle systemDemoSource
import * as v from "@thi.ng/vectors";

// immutable vector addition (1st arg is result)
v.add([], [1, 2, 3, 4], [10, 20, 30, 40]);
// [11, 22, 33, 44]

// mutable addition
// (if first arg (output) is null writes result to 2nd arg)
a = [1, 2, 3];
v.add(null, a, a);
// [2, 4, 6]

// multiply-add (o = a * b + c)
v.madd([], [10, 20], [0.5, 0.25], [1, 2]);
// [6, 7]

// multiply-add w/ scalar (o = a * n + b)
v.maddN([], [10, 20], 0.5, [1, 2]);
// [6, 12]

// scalar addition w/ arbitrary length & strided vector
v.addN([], gvec([0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0], 3, 1, 4), 10);
// [11, 12, 13]

// or operate on raw arrays directly...
// here the last 4 args define:
// out index, src index, out stride, src stride
v.addNS3(null, [0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0], 10, 1, 1, 4, 4)
// [0, 11, 0, 0, 0, 12, 0, 0, 0, 13, 0, 0, 0]

v.dist([1, 2], [100, 200]);
// 221.37072977247917

v.distManhattan([1, 2], [100, 200]);
// 297

v.distChebyshev([1, 2], [100, 200]);
// 198

v.mixN([], [1, 2], [10, 20], 0.5);
// [5.5, 11]

v.fromHomogeneous([], [100, 200, 0.5]);
// [200, 400]

v.swizzle4([], [1, 2], 1, 1, 0, 0);
// [ 2, 2, 1, 1 ]

v.hash([1, 2, 3])
// 2383338936

API

Generated API docs

Naming conventions

Wherever possible, each operation comes in different variations. All fixed size versions use optimized, loop-free implementations.

SuffixDescription
nonearbitrary length vector arg(s)
22d vector arg(s)
33d vector arg(s)
44d vector arg(s)
N22d vector(s) & scalar
N33d vector(s) & scalar
N44d vector(s) & scalar
Iarbitrary len, signed int vec
Uarbitrary len, unsigned int vec
I2 / I3 / I4fixed size signed int vec
U2 / U3 / U4fixed size signed int vec
NI / NUarbitrary len, signed int vec & scalar
NI2 / NI3 / NI4fixed size signed int vec & scalar
NU2 / NU3 / NU4fixed size unsigned int vec & scalar
S2 / S3 / S4fixed size strided vec
NS2 / NS3 / NS4fixed size strided vec & scalar
Carbitrary len vec, component wise args
C2 / C3 / C4fixed size vec, component wise args
CS2 / CS3 / CS4fixed size strided vec, component args

Constants

  • MAX2 / MAX3 / MAX4 - each component +Infinity
  • MIN2 / MIN3 / MIN4 - each component -Infinity
  • ONE2 / ONE3 / ONE4 - each component 1
  • ZERO2 / ZERO3 / ZERO4 - each component 0
  • X2 / X3 / X4 - positive X axis
  • Y2 / Y3 / Y4 - positive Y axis
  • Z3 / Z4 - positive Z axis
  • W4 - positive W axis

Component setters & copying

  • set / set2 / set3 / set4
  • setC / setC2 / setC3 / setC4 / setC6
  • setN / setN2 / setN3 / setN4
  • setS / setS2 / setS3 / setS4
  • setCS2 / setCS3 / setCS4
  • setNS2 / setNS3 / setNS4
  • copy
  • empty
  • one
  • zero

Component swizzling

  • swizzle2 / swizzle3 / swizzle4
  • setSwizzle1 / setSwizzle2 / setSwizzle3 / setSwizzle4
  • swapXY / swapXZ / swapYZ

Vector creation

Functions to create wrapped (strided) vector instances:

  • vec2 / vec2n
  • vec3 / vec3n
  • vec4 / vec4n
  • gvec

Wrap existing vanilla vectors:

  • asVec2 / asVec3 / asVec4

Vanilla vector (array) factories:

  • ones
  • zeroes
  • vecOf
  • setVN3 / setVN4
  • setVV4 / setVV6 / setVV9 / setVV16

Basic vector math

Vector / vector

Component wise op with 2 input vectors:

FunctionGenericFixedStridedIntComments
add2-4S2-S4I2-I4, U2-U4
div2-4S2-S4I2-I4, U2-U4
mul2-4S2-S4I2-I4, U2-U4
sub2-4S2-S4I2-I4, U2-U4
fmod2-4(GLSL behavior)
mod2-4(JS behavior)
pow2-4
// generic
add([], [1, 2, 3, 4, 5], [10, 20, 30, 40, 50]);
// [11, 22, 33, 44, 55]

// fixed size & packed
add2([], [1, 2], [10, 20])
// [11, 22]

// unsigned int
addU2([], [1, -2], [-10, 20])
// [4294967287, 18]

// strided
addS2([], [1,0,2,0], [0,10,0,0,0,20], 0, 0, 1, 1, 2, 4)
// [11, 22]

Vector / scalar

Component wise op with one input vector and single scalar:

FunctionGenericFixedStridedIntComments
addN2-4S2-S4I2-I4, U2-U4
divN2-4S2-S4I2-I4, U2-U4
mulN2-4S2-S4I2-I4, U2-U4
subN2-4S2-S4I2-I4, U2-U4
negsame as mulN(out, v, -1)
fmodN2-4(GLSL behavior)
modN2-4(JS behavior)
powN2-4

Combined operations

FunctionGenericFixedStridedIntComments
addm2-4S2-S4(a + b) * c
addmN2-4S2-S4(a + b) * n
madd2-4S2-S4a * n + c
maddN2-4S2-S4a * n + b
msub2-4S2-S4a * n - c
msubN2-4S2-S4a * n - b
subm2-4S2-S4(a - b) * c
submN2-4S2-S4(a - b) * n

Constraints

FunctionGenericFixedStridedIntComments
clamp2-4min(max(a, b), c)
clampN2-4min(max(a, n), m)
clamp01_2 - _4min(max(a, 0), 1)
clamp11_2 - _4min(max(a, -1), 1)
max2-4max(a, b)
min2-4min(a, b)

Cross product

FunctionGenericFixedStridedIntComments
cross2, 3S2, S32D version returns scalar
orthoNormal3
signedArea2

Dot product

FunctionGenericFixedStridedCwiseComments
dot2-4S2-S4C4, C6, C8

Interpolation

FunctionGenericFixedStridedIntComments
fit2-4
fit01_2 - _4
fit11_2 - _4
mix2-4S2 - S4
mixN2-4S2 - S4
mixBilinear2-4
mixCubic
mixQuadratic
smoothStep2-4
step2-4

Normalization / magnitude

FunctionGenericFixedStridedIntComments
limit
magS2-S4
magSq2-4S2-S4
normalizeS2-S4w/ opt target length

Distances

FunctionGenericFixedStridedIntComments
dist
distSq2-4
distChebyshev2-4
distManhattan2-4

Orientation

FunctionGenericFixedStridedIntComments
angleBetween2, 3
angleRatio
atan_22-4Math.atan2(y, x)
bisect2
cornerBisector
degrees2-4
directionnormalize(b - a)
faceForward
headingalias headingXY
headingXY
headingXZ
headingYZ
headingSegmentalias headingSegmentXY
headingSegmentXY
headingSegmentXZ
headingSegmentYZ
normalCCW2D only
normalCW2D only
perpendicularCCW2D only
perpendicularCW2D only
project
radians2-4
reflect
refract

Rotations

(Also see rotation matrices provided by @thi.ng/matrices)

FunctionGenericFixedStridedIntComments
rotationAroundAxis3
rotationAroundPoint2
rotateS2alias for rotateZ
rotateXS3
rotateYS3
rotateZS3

Polar / cartesian conversion

FunctionGenericFixedStridedIntComments
cartesian2, 32D/3D only
polar2, 32D/3D only

Randomness

All ops support custom PRNG impls based on the @thi.ng/random IRandom interface and use Math.random by default:

FunctionGenericFixedStridedIntComments
jitter
randMinMax2-4S2-S4
randNormS2-S4
random2-4S2-S4

Unary vector math ops

FunctionGenericFixedStridedIntComments
abs2-4
acos2-4
asin2-4
atan2-4Math.atan(y / x)
ceil2-4
cos2-4
cosh2-4
exp2-4
floor2-4
fract2-4
fromHomogeneous3, 43D/4D only
invert2-4
invSqrt2-4
isInf2-4
isNaN2-4
log2-4
major2-4
minor2-4
round2-4
sign2-4
sin2-4
sinh2-4
sqrt2-4
sum2-4
tan2-4
trunc2-4
wrap2-4

Vector array batch processing

Functions to transform flat / strided buffers w/ vector operations:

  • mapV / mapVN / mapVV / mapVVN / mapVVV

Comparison / equality

  • comparator2 / comparator3 / comparator4
  • equals / equals2 / equals3 / equals4
  • eqDelta / eqDelta2 / eqDelta3 / eqDelta4
  • eqDeltaS
  • eqDeltaArray

Bitwise operations (int / uint vec)

Arguments are assumed to be signed / unsigned ints. Results will be forced accordingly.

FunctionGenericFixedStridedIntComments
bitAndI2-I4, U2-U4
bitAndNI2-I4, U2-U4
bitNotI2-I4, U2-U4
bitOrI2-I4, U2-U4
bitOrNI2-I4, U2-U4
bitXorI2-I4, U2-U4
bitXorNI2-I4, U2-U4
lshiftI2-I4, U2-U4
rshiftI2-I4, U2-U4
lshiftNI2-I4, U2-U4
rshiftNI2-I4, U2-U4

Vector conversions / coercions

  • asIVec (2-4) - signed int vector
  • asUVec (2-4) - unsigned int vector
  • asBVec (2-4) - boolean vector
  • fromBVec (2-4) - coerces each component to 0/1

Boolean vector logic

FunctionGenericFixedStridedIntComments
logicAnd2-4
logicAndN2-4
logicOr2-4
logicOrN2-4
logicNot2-4
every2-4returns boolean
some2-4returns boolean
not2-4

Componentwise comparisons

All resulting in boolean vectors:

FunctionGenericFixedStridedIntComments
eq2-4
lt2-4
lte2-4
gt2-4
gte2-4
neq2-4

Hashing

  • hash

Code generator

  • compile / compileG / compileGHOF / compileHOF
  • defOp / defOpS / defFnOp / defHofOp
  • defMathNOp / defMathOp
  • vop

For more information about the code generator see:

Authors

Karsten Schmidt

License

© 2015 - 2020 Karsten Schmidt // Apache Software License 2.0

Generated using TypeDoc