[!NOTE] This is one of 192 standalone projects, maintained as part of the @thi.ng/umbrella monorepo and antiframework.
🚀 Please help me to work fulltime on these projects by sponsoring me on GitHub. Thank you! ❤️
 About
 Status
 Related packages
 Installation
 Dependencies
 Usage examples

API
 Basic usage
 Naming conventions
 Constants
 Component setters & copying
 Component swizzling
 Vector creation
 Basic vector math
 Combined operations
 Constraints
 Cross product
 Dot product
 Interpolation
 Normalization / magnitude
 Distances
 Orientation
 Rotations
 Polar / cartesian conversion
 Randomness
 Unary vector math ops
 Vector array batch processing
 Comparison / equality
 Bitwise operations (int / uint vec)
 Vector conversions / coercions
 Boolean vector logic
 Componentwise comparisons
 Hashing
 Code generator
 Authors
 License
Optimized 2d/3d/4d and arbitrary length vector operations, support for memory mapping/layouts.
Likely the most comprehensive vector library for TypeScript / JavaScript currently available.
This package provides over 875(!) largely code generated functions and supporting types to perform vector operations on fixed and arbitrarylength 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.
 Small & fast: The vast majority of functions are code generated with fixedsized versions not using any loops. Minified + gzipped, the entire package is ~11.8KB (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 multimethods, 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 multimethod base function, all fixedlength
optimized versions are exported too. E.g. If
add
performs vector addition on arbitrarylength vectors,add2
,add3
,add4
are the optimized version for fixedlength vectors...  Pluggable interface: The
VecAPI
interface defines objects of the ~70 most common vector operations implemented for specific vector sizes. Using this interface simplifies performancecritical use cases & algorithms which target different dimensions (e.g. 2d/3d), but should use the avaiable sizeoptimized vector ops. SeeVEC2
,VEC3
andVEC4
 Extensible: Custom vector ops can be defined in a similar manner using the provided code generation helpers (see vop.ts and emit.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 (usually) be used as output (i.e. for mutation).  Strided vector support is handled via the lightweight
Vec2/3/4
class wrappers and thegvec()
proxy (for generic, arbitrarylength vectors). These types behave like normal arrays (for read/write operations) and are also iterable. A subset of functions (suffixed withS
, 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 builtinMath.random()
will be used.
Partially ported from thi.ng/geomclj (Clojure) and c.thi.ng (C11).
STABLE  used in production
Search or submit any issues for this package
The introduction of seveveral standard libc math
functions to the
@thi.ng/math
package caused a behavior change of existing fmod()
function. For symmetry
reasons the same changes have been applied to this package...
 swap
fmod()
⇄mod()
, to align the latter with its GLSL counterpart  the new
fmod()
has standard libc behavior (same as JS%
operator)  add
remainder()
with standard libc behavior
 to avoid confusion, the arg order of
madd
andmaddN
functions have been updated to be compatible with the OpenCLmad
function and to generally follow the expanded name, i.e. multiplyadd:
madd([], a, b, c)
: beforea + 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
 @thi.ng/color  Arraybased color types, CSS parsing, conversions, transformations, declarative theme generation, gradients, presets
 @thi.ng/distance  Ndimensional distance metrics & Knearest neighborhoods for point queries
 @thi.ng/ecs  Entity Component System based around typed arrays & sparse sets
 @thi.ng/geom  Functional, polymorphic API for 2D geometry types & SVG generation
 @thi.ng/hdomcanvas  @thi.ng/hdom component wrapper for declarative canvas scenegraphs
 @thi.ng/imgui  Immediate mode GUI with flexible state handling & data only shape output
 @thi.ng/matrices  Matrix & quaternion operations for 2D/3D geometry processing
 @thi.ng/simd  WASM based SIMD vector operations for batch processing
 @thi.ng/soa  SOA & AOS memory mapped structured views with optional & extensible serialization
 @thi.ng/shaderastjs  Customizable JS codegen, compiler & runtime for @thi.ng/shaderast
 @thi.ng/vectorpools  Data structures for managing & working with strided, memory mapped vectors
 @thi.ng/webgl  WebGL & GLSL abstraction layer
yarn add @thi.ng/vectors
ESM import:
import * as vec from "@thi.ng/vectors";
Browser ESM import:
<script type="module" src="https://esm.run/@thi.ng/vectors"></script>
For Node.js REPL:
const vec = await import("@thi.ng/vectors");
Package sizes (brotli'd, pretreeshake): ESM: 13.88 KB
 @thi.ng/api
 @thi.ng/binary
 @thi.ng/checks
 @thi.ng/equiv
 @thi.ng/errors
 @thi.ng/math
 @thi.ng/memoize
 @thi.ng/random
 @thi.ng/strings
 @thi.ng/transducers
Several projects in this repo's /examples directory are using this package:
Screenshot  Description  Live demo  Source 

ASCII art raymarching with thi.ng/shaderast & thi.ng/textcanvas  Demo  Source  
Basic 2D boid simulation and spatial indexing neighbor lookups  Demo  Source  
Canvas based dial widget  Demo  Source  
Selfmodifying, animated typographic grid with emergent complex patterns  Demo  Source  
Interactive visualization of closest points on ellipses  Demo  Source  
Doodle w/ Knearest neighbor search result visualization  Demo  Source  
Knearest neighbor search in an hash grid  Demo  Source  
SVG path to SDF, applying deformation and converting back to SVG  Demo  Source  
Mouse gesture / stroke analysis, simplification, corner detection  Demo  Source  
Realtime analog clock demo  Demo  Source  
Interactive pattern drawing demo using transducers  Demo  Source  
2D Bezier curveguided particle system  Demo  Source  
Various hdomcanvas shape drawing examples & SVG conversion / export  Demo  Source  
Canvas based Immediate Mode GUI components  Demo  Source  
Animated sine plasma effect visualized using contour lines  Demo  Source  
kmeans clustering visualization  Demo  Source  
CLI util to visualize umbrella pkg stats  Source  
Animated, iterative polygon subdivisions & visualization  Demo  Source  
Quasirandom lattice generator  Demo  Source  
Unison wavetable synth with waveform editor  Demo  Source  
Steering behavior drawing with alphablended shapes  Demo  Source  
Minimal rdomcanvas animation  Demo  Source  
Animated Voronoi diagram, cubic splines & SVG download  Demo  Source  
2D scenegraph & shape picking  Demo  Source  
2D scenegraph & image map based geometry manipulation  Demo  Source  
Minimal shader graph developed during livestream #2  Demo  Source  
Fitting, transforming & plotting 10k data points per frame using SIMD  Demo  Source  
Entity Component System w/ 100k 3D particles  Demo  Source  
Compute cubic spline position & tangent using Dual Numbers  Demo  Source  
3D wireframe textmode demo  Demo  Source  
Visual comparison of biased vs. unbiased normal vectors projected on the surface of a sphere  Demo  Source  
WebGL multicolored cube mesh  Demo  Source  
Drawing to floating point offscreen / multipass shader pipeline  Demo  Source  
WebGL instancing, animated grid  Demo  Source  
WebGL MSDF text rendering & particle system  Demo  Source 
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]
// multiplyadd (o = a * b + c)
v.madd([], [10, 20], [0.5, 0.25], [1, 2]);
// [6, 7]
// multiplyadd 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
Using the
VecAPI
implementation objects to use sizeoptimized vector ops in a pluggable manner
(this is in addition/alternative to using the standard set of polymorphic
functions for similar results).
import { VEC2, VEC3, type Vec, type VecAPI } from "@thi.ng/vectors";
interface Particle {
pos: Vec;
dir: Vec;
targetDir: Vec;
speed: number;
turnSpeed: number;
}
const updateParticle = (p: Particle, { maddN, mixN, normalize }: VecAPI) => {
// interpolate current direction toward target dir
mixN(null, p.dir, p.targetDir, p.turnSpeed);
// normalize direction
normalize(null, p.dir);
// add scaled direction to position (and store as new position)
return maddN(p.pos, p.dir, p.speed, p.pos);
};
// 2d version
let p2d: Particle = {
pos: [10, 20], dir: [0, 1], targetDir: [1, 0], speed: 5, turnSpeed: 0.1,
};
updateParticle(p2d, VEC2);
// [ 10.552, 24.969 ]
// 3d version
let p3d: Particle = {
pos: [10, 20, 30], dir: [0, 1, 0], targetDir: [0, 0, 1], speed: 5, turnSpeed: 0.1,
};
updateParticle(p3d, VEC3);
// [ 10, 24.969, 30.552 ]
Wherever possible, each operation comes in different variations. All fixed size versions use optimized, loopfree implementations.
Suffix  Description 

none  arbitrary length vector arg(s) 
2  2d vector arg(s) 
3  3d vector arg(s) 
4  4d vector arg(s) 
N2  2d vector(s) & scalar 
N3  3d vector(s) & scalar 
N4  4d vector(s) & scalar 
I  arbitrary len, signed int vec 
U  arbitrary len, unsigned int vec 
I2 / I3 / I4  fixed size signed int vec 
U2 / U3 / U4  fixed size signed int vec 
NI / NU  arbitrary len, signed int vec & scalar 
NI2 / NI3 / NI4  fixed size signed int vec & scalar 
NU2 / NU3 / NU4  fixed size unsigned int vec & scalar 
S2 / S3 / S4  fixed size strided vec 
NS2 / NS3 / NS4  fixed size strided vec & scalar 
C  arbitrary len vec, component wise args 
C2 / C3 / C4  fixed size vec, component wise args 
CS2 / CS3 / CS4  fixed size strided vec, component args 

MAX2
/MAX3
/MAX4
 each component+Infinity

MIN2
/MIN3
/MIN4
 each componentInfinity

ONE2
/ONE3
/ONE4
 each component1

ZERO2
/ZERO3
/ZERO4
 each component0

X2
/X3
/X4
 positive X axis 
Y2
/Y3
/Y4
 positive Y axis 
Z3
/Z4
 positive Z axis 
W4
 positive W axis

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

swizzle2
/swizzle3
/swizzle4

setSwizzle1
/setSwizzle2
/setSwizzle3
/setSwizzle4

swapXY
/swapXZ
/swapYZ
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
Component wise op with 2 input vectors:
Function  Generic  Fixed  Strided  Int  Comments 

add 
✓  24  S2S4  I2I4, U2U4  
div 
✓  24  S2S4  I2I4, U2U4  
mul 
✓  24  S2S4  I2I4, U2U4  
sub 
✓  24  S2S4  I2I4, U2U4  
fmod 
✓  24  (C/JS behavior)  
mod 
✓  24  (GLSL behavior)  
pow 
✓  24  
remainder 
✓  24  (C behavior) 
import { add, add2, addU2, addS2 } from "@thi.ng/vectors";
// 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]
Component wise op with one input vector and single scalar:
Function  Generic  Fixed  Strided  Int  Comments 

addN 
✓  24  S2S4  I2I4, U2U4  
divN 
✓  24  S2S4  I2I4, U2U4  
mulN 
✓  24  S2S4  I2I4, U2U4  
subN 
✓  24  S2S4  I2I4, U2U4  
neg 
✓  same as mulN(out, v, 1)


fmodN 
✓  24  (C/JS behavior)  
modN 
✓  24  (GLSL behavior)  
powN 
✓  24  
remainderN 
✓  24  (C behavior)  
roundN 
✓  24 
Function  Generic  Fixed  Strided  Int  Comments 

addm 
✓  24  S2S4  (a + b) * c  
addmN 
✓  24  S2S4  (a + b) * n  
madd 
✓  24  S2S4  a * n + c  
maddN 
✓  24  S2S4  a * n + b  
msub 
✓  24  S2S4  a * n  c  
msubN 
✓  24  S2S4  a * n  b  
subm 
✓  24  S2S4  (a  b) * c  
submN 
✓  24  S2S4  (a  b) * n 
Function  Generic  Fixed  Strided  Int  Comments 

clamp 
✓  24  min(max(a, b), c) 

clampN 
✓  24  min(max(a, n), m) 

clamp01 
✓  _2  _4  min(max(a, 0), 1) 

clamp11 
✓  _2  _4  min(max(a, 1), 1) 

max 
✓  24  max(a, b) 

min 
✓  24  min(a, b) 
Function  Generic  Fixed  Strided  Int  Comments 

cross 
2, 3  S2, S3  2D version returns scalar  
orthoNormal 
3  
signedArea 
2 
Function  Generic  Fixed  Strided  Cwise  Comments 

dot 
✓  24  S2S4  C4, C6, C8 
Function  Generic  Fixed  Strided  Int  Comments 

fit 
✓  24  
fit01 
✓  _2  _4  
fit11 
✓  _2  _4  
mix 
✓  24  S2  S4  
mixN 
✓  24  S2  S4  
mixBilinear 
✓  24  
mixCubic 
✓  
mixQuadratic 
✓  
smoothStep 
✓  24  
step 
✓  24 
Function  Generic  Fixed  Strided  Int  Comments 

limit 
✓  
mag 
✓  S2S4  
magSq 
✓  24  S2S4  
normalize 
✓  S2S4  w/ opt target length 
Function  Generic  Fixed  Strided  Int  Comments 

dist 
✓  
distSq 
✓  24  
distChebyshev 
✓  24  
distHaversineLatLon 
2  lat/lon coordinates  
distHaversineLonLat 
2  lon/lat coordinates  
distManhattan 
✓  24  
pointOnRay 
✓  23  point at distance 
Function  Generic  Fixed  Strided  Int  Comments 

angleBetween 
2, 3  
angleRatio 
✓  
atan_2 
✓  24  Math.atan2(y, x) 

bisect 
2  
cornerBisector 
✓  
degrees 
✓  24  
direction 
✓  normalize(b  a)  
faceForward 
✓  
heading 
✓  alias headingXY


headingXY 
✓  
headingXZ 
✓  
headingYZ 
✓  
headingSegment 
✓  alias headingSegmentXY


headingSegmentXY 
✓  
headingSegmentXZ 
✓  
headingSegmentYZ 
✓  
normalCCW 
2D only  
normalCW 
2D only  
perpendicularCCW 
2D only  
perpendicularCW 
2D only  
project 
✓  
radians 
✓  24  
reflect 
✓  
refract 
✓ 
(Also see rotation matrices provided by @thi.ng/matrices)
Function  Generic  Fixed  Strided  Int  Comments 

rotationAroundAxis 
3  
rotationAroundPoint 
2  
rotate 
S2  alias for rotateZ


rotateX 
S3  
rotateY 
S3  
rotateZ 
S3 
Function  Generic  Fixed  Strided  Int  Comments 

cartesian 
✓  2, 3  2D/3D only  
polar 
✓  2, 3  2D/3D only 
All ops support custom PRNG impls based on the
@thi.ng/random
IRandom
interface and use Math.random
by default:
Function  Generic  Fixed  Strided  Int  Comments 

jitter 
✓  
randMinMax 
✓  24  S2S4  
randNorm 
✓  24  S2S4  
randNormDistrib 
✓  24  S2S4  
random 
✓  24  S2S4  
randomDistrib 
✓  24  S2S4 
Function  Generic  Fixed  Strided  Int  Comments 

abs 
✓  24  
acos 
✓  24  
asin 
✓  24  
atan 
✓  24  Math.atan(y / x) 

ceil 
✓  24  
cos 
✓  24  
cosh 
✓  24  
exp 
✓  24  
floor 
✓  24  
fract 
✓  24  
fromHomogeneous 
✓  3, 4  3D/4D only  
invert 
✓  24  
invSqrt 
✓  24  
isInf 
✓  24  
isNaN 
✓  24  
log 
✓  24  
major 
✓  24  
minor 
✓  24  
round 
✓  24  
sign 
✓  24  
sin 
✓  24  
sinh 
✓  24  
sqrt 
✓  24  
sum 
✓  24  
tan 
✓  24  
trunc 
✓  24  
wrap 
✓  24 
Functions to transform flat / strided buffers w/ vector operations:

mapV
/mapVN
/mapVV
/mapVVN
/mapVVV

mean
/median

minBounds
/maxBounds

comparator2
/comparator3
/comparator4

equals
/equals2
/equals3
/equals4

eqDelta
/eqDelta2
/eqDelta3
/eqDelta4
eqDeltaS
eqDeltaArray
Arguments are assumed to be signed / unsigned ints. Results will be forced accordingly.
Function  Generic  Fixed  Strided  Int  Comments 

bitAnd 
✓  I2I4, U2U4  
bitAndN 
✓  I2I4, U2U4  
bitNot 
✓  I2I4, U2U4  
bitOr 
✓  I2I4, U2U4  
bitOrN 
✓  I2I4, U2U4  
bitXor 
✓  I2I4, U2U4  
bitXorN 
✓  I2I4, U2U4  
lshift 
✓  I2I4, U2U4  
rshift 
✓  I2I4, U2U4  
lshiftN 
✓  I2I4, U2U4  
rshiftN 
✓  I2I4, U2U4 

asIVec
(24)  signed int vector 
asUVec
(24)  unsigned int vector 
asBVec
(24)  boolean vector 
fromBVec
(24)  coerces each component to 0/1
Function  Generic  Fixed  Strided  Int  Comments 

logicAnd 
✓  24  
logicAndN 
✓  24  
logicOr 
✓  24  
logicOrN 
✓  24  
logicNot 
✓  24  
every 
✓  24  returns boolean


some 
✓  24  returns boolean


not 
✓  24 
All resulting in boolean vectors:
Function  Generic  Fixed  Strided  Int  Comments 

eq 
✓  24  
lt 
✓  24  
lte 
✓  24  
gt 
✓  24  
gte 
✓  24  
neq 
✓  24 
hash

compile
/compileG
/compileGHOF
/compileHOF

defOp
/defOpS
/defFnOp
/defHofOp

defMathNOp
/defMathOp
vop
For more information about the code generator see:
If this project contributes to an academic publication, please cite it as:
@misc{thingvectors,
title = "@thi.ng/vectors",
author = "Karsten Schmidt",
note = "https://thi.ng/vectors",
year = 2015
}
© 2015  2024 Karsten Schmidt // Apache License 2.0