UNPKG

@thi.ng/vectors

Version:

Optimized 2d/3d/4d and arbitrary length vector operations, support for memory mapping/layouts

323 lines 14.1 kB
import type { ArrayLikeIterable, Fn, Fn0, Fn2, Fn3, Fn4, Fn6, Fn7, FnU2, ICopy, IEmpty, IEqualsDelta, ILength, Maybe, NumericArray, Tuple, TypedArray } from "@thi.ng/api"; import type { IRandom } from "@thi.ng/random"; export interface Vec<T = number> extends Iterable<T>, ILength { [id: number]: T; } export type BVec = Vec<boolean>; export type ReadonlyVec<T = number> = ArrayLikeIterable<T>; export type ReadonlyBVec = ReadonlyVec<boolean>; export type Vec2Like = Tuple<number, 2> | TypedArray; export type Vec3Like = Tuple<number, 3> | TypedArray; export type Vec4Like = Tuple<number, 4> | TypedArray; export type BVec2Like = Tuple<boolean, 2>; export type BVec3Like = Tuple<boolean, 3>; export type BVec4Like = Tuple<boolean, 4>; export interface StridedVec { buf: NumericArray; offset: number; stride: number; } export interface IVector<T> extends Vec, ICopy<T>, ICopyView<T>, IEmpty<T>, IEqualsDelta<T>, StridedVec { } export interface ICopyView<T> { copyView(): T; } export interface VectorConstructor<T> { new (buf: NumericArray, offset?: number, stride?: number): T; } export interface MultiVecOp<VOP> { /** * Adds / overwrites implementation for given vector size. * * @param dim - * @param op - */ add(dim: number, op: VOP): VOP; /** * Adds / overwrites default implementation (SHOULD support * arbitrary vector sizes). * * @param op - */ default(op: VOP): VOP; /** * Returns implementation for given vector size or default * implementation. * * @param dim - */ impl(dim?: number): Maybe<VOP>; } export type VecPair<T = number> = [Vec<T>, Vec<T>]; export type VecOpV<A = number, B = A> = Fn2<Vec<B> | null, ReadonlyVec<A>, Vec<B>>; export type VecOpN = Fn2<Vec, number, Vec>; export type VecOpVV<A = number, B = A> = Fn3<Vec<B> | null, ReadonlyVec<A>, ReadonlyVec<A>, Vec<B>>; export type VecOpVN = Fn3<Vec | null, ReadonlyVec, number, Vec>; export type VecOpVVV<A = number, B = A> = Fn4<Vec<B> | null, ReadonlyVec<A>, ReadonlyVec<A>, ReadonlyVec<A>, Vec<B>>; export type VecOpVVN = Fn4<Vec | null, ReadonlyVec, ReadonlyVec, number, Vec>; export type VecOpVNV = Fn4<Vec | null, ReadonlyVec, number, ReadonlyVec, Vec>; export type VecOpVNN = Fn4<Vec | null, ReadonlyVec, number, number, Vec>; export type VecOpVVVVV<A = number, B = A> = Fn6<Vec<B> | null, ReadonlyVec<A>, ReadonlyVec<A>, ReadonlyVec<A>, ReadonlyVec<A>, ReadonlyVec<A>, Vec<B>>; export type VecOpVVVVNN = Fn7<Vec | null, ReadonlyVec, ReadonlyVec, ReadonlyVec, ReadonlyVec, number, number, Vec>; export type VecOpVO<T> = (out: Vec | null, a: ReadonlyVec, b?: T) => Vec; export type VecOpVVO<O> = (out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, c?: O) => Vec; export type VecOpOO<A, B> = (out: Vec | null, a?: A, b?: B) => Vec; export type VecOpOOO<A, B, C> = (out: Vec | null, a?: A, b?: B, c?: C) => Vec; export type VecOpNO<O> = (out: Vec | null, a: number, b?: O) => Vec; export type VecOpNNO<O> = (out: Vec | null, a: number, b: number, c?: O) => Vec; export type VecOpRoV<T> = Fn<ReadonlyVec, T>; export type VecOpRoVV<T> = FnU2<ReadonlyVec, T>; export type VecOpRoVVO<T, O> = (a: ReadonlyVec, b: ReadonlyVec, c?: O) => T; export type VecOpFN = (out: Vec | null, fn: Fn0<number>, n?: number) => Vec; export type VecOpFNO = (out: Vec | null, fn?: Fn0<number>, n?: number) => Vec; export type VecOpNFO = (out: Vec | null, n?: number, fn?: Fn0<number>) => Vec; export type VecOpSV = (out: Vec | null, a: ReadonlyVec, io?: number, ia?: number, so?: number, sa?: number) => Vec; export type VecOpSGV = (out: Vec | null, a: ReadonlyVec, num: number, io?: number, ia?: number, so?: number, sa?: number) => Vec; export type VecOpSN = (out: Vec | null, n: number, io?: number, so?: number) => Vec; export type VecOpSGN = (out: Vec | null, n: number, num: number, io?: number, so?: number) => Vec; export type VecOpSVN = (out: Vec | null, a: ReadonlyVec, n: number, io?: number, ia?: number, so?: number, sa?: number) => Vec; export type VecOpSGVN = (out: Vec | null, a: ReadonlyVec, n: number, num: number, io?: number, ia?: number, so?: number, sa?: number) => Vec; export type VecOpSVV = (out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, io?: number, ia?: number, ib?: number, so?: number, sa?: number, sb?: number) => Vec; export type VecOpSGVV = (out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, num: number, io?: number, ia?: number, ib?: number, so?: number, sa?: number, sb?: number) => Vec; export type VecOpSVNV = (out: Vec | null, a: ReadonlyVec, n: number, b: ReadonlyVec, io?: number, ia?: number, ib?: number, so?: number, sa?: number, sb?: number) => Vec; export type VecOpSGVNV = (out: Vec | null, a: ReadonlyVec, n: number, b: ReadonlyVec, num: number, io?: number, ia?: number, ib?: number, so?: number, sa?: number, sb?: number) => Vec; export type VecOpSVVN = (out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, n: number, io?: number, ia?: number, ib?: number, so?: number, sa?: number, sb?: number) => Vec; export type VecOpSGVVN = (out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, n: number, num: number, io?: number, ia?: number, ib?: number, so?: number, sa?: number, sb?: number) => Vec; export type VecOpSVVV = (out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, io?: number, ia?: number, ib?: number, ic?: number, so?: number, sa?: number, sb?: number, sc?: number) => Vec; export type VecOpSGVVV = (out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, num: number, io?: number, ia?: number, ib?: number, ic?: number, so?: number, sa?: number, sb?: number, sc?: number) => Vec; export type VecOpSRoV<T> = (a: ReadonlyVec, ia?: number, sa?: number) => T; export type VecOpSGRoV<T> = (a: ReadonlyVec, num: number, ia?: number, sa?: number) => T; export type VecOpSRoVV<T> = (a: ReadonlyVec, b: ReadonlyVec, ia?: number, ib?: number, sa?: number, sb?: number) => T; export type VecOpSVO<T> = (out: Vec | null, a: ReadonlyVec, b?: T, io?: number, ia?: number, so?: number, sa?: number) => Vec; export type VecOpSGVO<O> = (out: Vec | null, a: ReadonlyVec, num: number, b?: O, io?: number, ia?: number, so?: number, sa?: number) => Vec; export type VecOpSOO<A, B> = (a: Vec | null, opt1?: A, opt2?: B, ia?: number, sa?: number) => Vec; export type VecOpSGOO<A, B> = (a: Vec | null, num: number, opt1?: A, opt2?: B, ia?: number, sa?: number) => Vec; export type VecOpSOOO<A, B, C> = (a: Vec | null, opt1?: A, opt2?: B, opt3?: C, ia?: number, sa?: number) => Vec; export type VecOpSGOOO<A, B, C> = (a: Vec | null, num: number, opt1?: A, opt2?: B, opt3?: C, ia?: number, sa?: number) => Vec; export type VecOpSVVO<O> = (out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, opt?: O, io?: number, ia?: number, ib?: number, so?: number, sa?: number, sb?: number) => Vec; export type VecOpSGVVO<O> = (out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, num: number, opt?: O, io?: number, ia?: number, ib?: number, so?: number, sa?: number, sb?: number) => Vec; export type VecOpSGFN = (out: Vec | null, num: number, fn: Fn0<number>, n?: number, io?: number, so?: number) => Vec; export type VecOpSFN = (out: Vec | null, fn: Fn0<number>, n?: number, io?: number, so?: number) => Vec; export type MultiVecOpImpl<T> = T & MultiVecOp<T>; export type MultiVecOpV<A = number, B = A> = MultiVecOpImpl<VecOpV<A, B>>; export type MultiVecOpN = MultiVecOpImpl<VecOpN>; export type MultiVecOpVV<A = number, B = A> = MultiVecOpImpl<VecOpVV<A, B>>; export type MultiVecOpVN = MultiVecOpImpl<VecOpVN>; export type MultiVecOpVVV<A = number, B = A> = MultiVecOpImpl<VecOpVVV<A, B>>; export type MultiVecOpVVN = MultiVecOpImpl<VecOpVVN>; export type MultiVecOpVNV = MultiVecOpImpl<VecOpVNV>; export type MultiVecOpVNN = MultiVecOpImpl<VecOpVNN>; export type MultiVecOpVVVVV<A = number, B = A> = MultiVecOpImpl<VecOpVVVVV<A, B>>; export type MultiVecOpVVVVNN = MultiVecOpImpl<VecOpVVVVNN>; export type MultiVecOpVO<O> = MultiVecOpImpl<VecOpVO<O>>; export type MultiVecOpVVO<O> = MultiVecOpImpl<VecOpVVO<O>>; export type MultiVecOpOO<A, B> = MultiVecOpImpl<VecOpOO<A, B>>; export type MultiVecOpOOO<A, B, C> = MultiVecOpImpl<VecOpOOO<A, B, C>>; export type MultiVecOpNNO<O> = MultiVecOpImpl<VecOpNNO<O>>; export type MultiVecOpRoV<T> = MultiVecOpImpl<VecOpRoV<T>>; export type MultiVecOpRoVV<T> = MultiVecOpImpl<VecOpRoVV<T>>; export type MultiVecOpRoVVO<T, O> = MultiVecOpImpl<VecOpRoVVO<T, O>>; export type MultiVecOpFN = MultiVecOpImpl<VecOpFN>; export type MultiVecOpFNO = MultiVecOpImpl<VecOpFNO>; export type MultiVecOpNFO = MultiVecOpImpl<VecOpNFO>; export type MultiVecOpSFN = MultiVecOpImpl<VecOpSFN>; export type BVecOpRoV<T> = Fn<ReadonlyBVec, T>; export type BVecOpV = VecOpV<boolean>; export type BVecOpVV = VecOpVV<boolean>; export type BVecOpVN = Fn3<BVec | null, ReadonlyBVec, boolean, BVec>; export type ToBVecOpV = VecOpV<number, boolean>; export type FromBVecOpV = VecOpV<boolean, number>; export type MultiBVecOpV = MultiVecOpImpl<BVecOpV>; export type MultiBVecOpVV = MultiVecOpImpl<BVecOpVV>; export type MultiBVecOpVN = MultiVecOpImpl<BVecOpVN>; export type MultiBVecOpRoV<T> = MultiVecOpImpl<BVecOpRoV<T>>; export type MultiToBVecOpV = MultiVecOpImpl<ToBVecOpV>; export type MultiFromBVecOpV = MultiVecOpImpl<FromBVecOpV>; export type CompareOp = Fn3<BVec | null, ReadonlyVec, ReadonlyVec, BVec>; export type MultiCompareOp = MultiVecOpImpl<CompareOp>; export type DistanceFn = VecOpRoVV<number>; /** * An object of the ~70 most common vector operations implemented for a specific * vector size. See {@link VEC2}, {@link VEC3}, {@link VEC4}. * * @remarks * Using this interface simplifies other performance-critical use * cases/algorithms which target different dimensionalities (e.g. 2d/3d), but * which should use the size-optimized vector operations (avoiding the small * overhead of their nD vector versions which would likely be used otherwise). * * @example * ```ts tangle:../export/vec-api.ts * 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, api: VecAPI) => { * // interpolate current direction toward target dir * api.mixN(null, p.dir, p.targetDir, p.turnSpeed); * // normalize direction * api.normalize(null, p.dir); * // add scaled direction to position (and store as new position) * return api.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 * }; * * console.log( * 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 * }; * * console.log( * updateParticle(p3d, VEC3) * ); * // [ 10, 24.969, 30.552 ] * ``` */ export interface VecAPI { ZERO: ReadonlyVec; ONE: ReadonlyVec; zeroes: Fn0<Vec>; ones: Fn0<Vec>; abs: VecOpV; acos: VecOpV; add: VecOpVV; addN: VecOpVN; addm: VecOpVVV; addmN: VecOpVVN; asin: VecOpV; atan: VecOpV; atan2: VecOpVV; ceil: VecOpV; clamp: VecOpVVV; clampN: VecOpVNN; clamp01: VecOpV; cos: VecOpV; degrees: VecOpV; dist: DistanceFn; distSq: DistanceFn; div: VecOpVV; divN: VecOpVN; dot: VecOpRoVV<number>; eqDelta: VecOpRoVVO<boolean, number>; equals: VecOpRoVV<boolean>; exp: VecOpV; exp2: VecOpV; fit: VecOpVVVVV; fit01: VecOpVVV; floor: VecOpV; fmod: VecOpVV; fract: VecOpV; invSqrt: VecOpV; mag: VecOpRoV<number>; magSq: VecOpRoV<number>; limit: VecOpVN; log: VecOpV; log2: VecOpV; madd: VecOpVVV; maddN: VecOpVNV; major: VecOpRoV<number>; max: VecOpVV; min: VecOpVV; minor: VecOpRoV<number>; mix: VecOpVVV; mixN: VecOpVVN; mod: VecOpVV; modN: VecOpVN; msub: VecOpVVV; msubN: VecOpVNV; mul: VecOpVV; mulN: VecOpVN; normalize: VecOpVO<number>; pow: VecOpVV; powN: VecOpVN; radians: VecOpV; random: VecOpOOO<number, number, IRandom>; randomDistrib: VecOpFNO; randMinMax: VecOpVVO<IRandom>; randNorm: VecOpOO<number, IRandom>; randNormDistrib: VecOpNFO; round: VecOpVV; set: VecOpV; setN: VecOpN; sign: VecOpV; sin: VecOpV; smoothstep: VecOpVVV; sqrt: VecOpV; step: VecOpVV; sub: VecOpVV; subN: VecOpVN; subm: VecOpVVV; submN: VecOpVVN; tan: VecOpV; trunc: VecOpV; eq: CompareOp; neq: CompareOp; gt: CompareOp; gte: CompareOp; lt: CompareOp; lte: CompareOp; } export interface ToStringOpts { /** * Number of fractional digits * * @defaultValue 3 */ prec: number; /** * If given, each formatted vector component will be padded to given number * of characters. */ width: number; /** * Inter-component delimiter. * * @defaultValue ", " */ delim: string; /** * Prefix/suffix wrapper strings. * * @defaultValue "[" and "]" */ wrap: ArrayLike<string>; } export declare const MIN2: ReadonlyVec; export declare const MAX2: ReadonlyVec; export declare const ONE2: ReadonlyVec; export declare const ZERO2: ReadonlyVec; export declare const X2: ReadonlyVec; export declare const Y2: ReadonlyVec; export declare const MIN3: ReadonlyVec; export declare const MAX3: ReadonlyVec; export declare const ONE3: ReadonlyVec; export declare const ZERO3: ReadonlyVec; export declare const X3: ReadonlyVec; export declare const Y3: ReadonlyVec; export declare const Z3: ReadonlyVec; export declare const MIN4: ReadonlyVec; export declare const MAX4: ReadonlyVec; export declare const ONE4: ReadonlyVec; export declare const ZERO4: ReadonlyVec; export declare const X4: ReadonlyVec; export declare const Y4: ReadonlyVec; export declare const Z4: ReadonlyVec; export declare const W4: ReadonlyVec; //# sourceMappingURL=api.d.ts.map