High-performance Apple Accelerate framework bindings for Node.js. Get up to 305x faster matrix operations and 5-10x faster vector operations on Apple Silicon (M1/M2/M3/M4).
80+ hardware-accelerated functions including BLAS, vDSP, and vForce operations.
Node.js doesn't natively use Apple's Accelerate framework, which provides hardware-optimized routines for numerical computing. This addon exposes Accelerate's BLAS (matrix operations) and vDSP (vector/signal processing) to JavaScript, giving you direct access to:
- AMX (Apple Matrix coprocessor) - Hardware matrix acceleration
- NEON SIMD - Vector processing
- Optimized FFT - Fast Fourier Transform
Note: This package only works on macOS because it uses Apple's Accelerate framework. If you're on Linux ARM64 (Raspberry Pi, AWS Graviton, etc.), consider using OpenBLAS, Eigen, or BLIS instead.
Real benchmarks on Apple M4 Max:
| Operation | Pure JavaScript | node-accelerate | Speedup |
|---|---|---|---|
| Matrix Multiply (500×500) | 90.5 ms | 0.30 ms | 305x |
| Vector Dot Product (1M) | 0.65 ms | 0.13 ms | 4.9x |
| Vector Sum (1M) | 0.58 ms | 0.07 ms | 7.8x |
| Vector Add (1M) | 0.44 ms | 0.19 ms | 2.2x |
| Vector Sin (10k) | 0.062 ms | 0.008 ms | 7.6x |
- Matrix multiplication (double & single precision)
- Matrix-vector multiplication
- Matrix transpose
- AXPY, copy, swap operations
- Vector norms and rotations
- Basic operations: add, subtract, multiply, divide, scale, negate
- Dot product, norm, absolute sum
- Element-wise operations: abs, square, sqrt, power, reciprocal
- Multiply-add operations: vma, vmsa
- Normalization to unit length
- Vector utilities: fill, ramp, clear, reverse, copy, swap
- Standard trig: sin, cos, tan (5-10x faster than Math functions)
- Inverse trig: asin, acos, atan, atan2
- Hyperbolic: sinh, cosh, tanh
- Process 1000s of values in microseconds
- exp - Natural exponential
- log, log10 - Natural and base-10 logarithms
- pow - Element-wise power
- Reciprocal and inverse square root
- Basic stats: sum, mean, min, max, minmax
- Variance & standard deviation
- RMS (Root Mean Square)
- Sum of squares, mean magnitude, mean square
- Max/min magnitude
- FFT/IFFT - Fast Fourier Transform (forward & inverse)
- Convolution - 1D convolution for filtering
- Cross-correlation - Signal similarity analysis
- Window functions: Hamming, Hanning, Blackman
- 10-50x faster than pure JavaScript FFT
- Clipping & limiting - Constrain values to range
- Thresholding - Apply threshold to data
- Interpolation - Linear interpolation and lerp
- Rounding: ceil, floor, trunc
- Sign manipulation: copysign
- ✅ Hardware acceleration via AMX & NEON
- ✅ Double precision (Float64Array)
- ✅ Single precision (Float32Array) for matrix ops
- ✅ Zero-copy operations where possible
- ✅ Optimized for Apple Silicon
- ✅ 80+ functions total
npm install @digitaldefiance/node-accelerateRequirements:
- macOS (Apple Silicon: M1/M2/M3/M4 or Intel)
- Node.js >= 18.0.0
- Xcode Command Line Tools
If you don't have Xcode Command Line Tools installed:
xcode-select --installThe package will automatically check your platform during installation. If you see errors:
"node-accelerate requires macOS"
- This package only works on macOS due to Apple's Accelerate framework
- Not supported on Linux or Windows
"Xcode Command Line Tools may not be installed"
- Run:
xcode-select --install - Follow the prompts to install
"Failed to load native module"
- Try rebuilding:
npm rebuild @digitaldefiance/node-accelerate - Ensure Xcode Command Line Tools are installed
node -e "const a = require('@digitaldefiance/node-accelerate'); console.log('✓ Works!')"constaccelerate=require('@digitaldefiance/node-accelerate');// Matrix multiplication: C = A × BconstM=1000,K=1000,N=1000;constA=newFloat64Array(M*K);constB=newFloat64Array(K*N);constC=newFloat64Array(M*N);// Fill with random datafor(leti=0;i<A.length;i++)A[i]=Math.random();for(leti=0;i<B.length;i++)B[i]=Math.random();// Hardware-accelerated matrix multiplicationaccelerate.matmul(A,B,C,M,K,N);// Vector operationsconstvec1=newFloat64Array(1000000);constvec2=newFloat64Array(1000000);constresult=newFloat64Array(1000000);for(leti=0;i<vec1.length;i++){vec1[i]=Math.random();vec2[i]=Math.random();}accelerate.vadd(vec1,vec2,result);// result = vec1 + vec2accelerate.vmul(vec1,vec2,result);// result = vec1 * vec2constdotProduct=accelerate.dot(vec1,vec2);constsum=accelerate.sum(vec1);constmean=accelerate.mean(vec1);// Statistical operationsconst{ min, max }=accelerate.minmax(vec1);constvariance=accelerate.variance(vec1);conststddev=accelerate.stddev(vec1);// Trigonometric functions (vectorized)constangles=newFloat64Array(1000);constsines=newFloat64Array(1000);constcosines=newFloat64Array(1000);for(leti=0;i<1000;i++){angles[i]=(i/1000)*2*Math.PI;}accelerate.vsin(angles,sines);accelerate.vcos(angles,cosines);// Signal processingconstsignal=newFloat64Array(65536);for(leti=0;i<signal.length;i++){signal[i]=Math.sin(2*Math.PI*i/signal.length);}// Apply window and compute FFTconstwindow=accelerate.hanning(signal.length);constwindowed=newFloat64Array(signal.length);accelerate.vmul(signal,window,windowed);constspectrum=accelerate.fft(windowed);console.log(spectrum.real,spectrum.imag);// Inverse FFTconstreconstructed=accelerate.ifft(spectrum.real,spectrum.imag);// Convolution for filteringconstkernel=newFloat64Array([0.25,0.5,0.25]);// Moving averageconstfiltered=newFloat64Array(signal.length-kernel.length+1);accelerate.conv(signal,kernel,filtered);// Data processingconstdata=newFloat64Array(1000);for(leti=0;i<data.length;i++){data[i]=Math.random()*200-100;}// Clip outliersconstclipped=newFloat64Array(1000);accelerate.vclip(data,clipped,-50,50);// Matrix transposeconstmatrix=newFloat64Array([1,2,3,4,5,6]);// 2×3consttransposed=newFloat64Array(6);// 3×2accelerate.transpose(matrix,transposed,2,3);Check out the examples/ directory for complete working examples:
machine-learning.js- Neural network operations, softmax, ReLUsignal-processing.js- FFT, filtering, spectral analysisstatistical-operations.js- Mean, variance, std dev, z-scorestrigonometric-functions.js- Vectorized trig operationssignal-processing-advanced.js- Convolution, correlation, windowingmathematical-functions.js- Exp, log, power functionsdata-processing.js- Clipping, thresholding, interpolationmatrix-multiply.js- Matrix operations and benchmarksvector-operations.js- Vector arithmetic examples
Run any example:
node examples/statistical-operations.js
node examples/signal-processing-advanced.jsMatrix multiplication: C = A × B
A: Float64Array - First matrix (M × K) in row-major orderB: Float64Array - Second matrix (K × N) in row-major orderC: Float64Array - Output matrix (M × N) in row-major orderM: number - Rows in A and CK: number - Columns in A, rows in BN: number - Columns in B and C- Returns: Float64Array (C)
Example:
constM=100,K=100,N=100;constA=newFloat64Array(M*K);constB=newFloat64Array(K*N);constC=newFloat64Array(M*N);// Fill A and B...accelerate.matmul(A,B,C,M,K,N);Single-precision matrix multiplication (uses Float32Array)
Same parameters as matmul but with Float32Array instead of Float64Array.
Matrix-vector multiplication: y = A × x
A: Float64Array - Matrix (M × N) in row-major orderx: Float64Array - Input vector (N elements)y: Float64Array - Output vector (M elements)M: number - Rows in AN: number - Columns in A- Returns: Float64Array (y)
Matrix transpose: B = A^T
A: Float64Array - Input matrix (rows × cols) in row-major orderB: Float64Array - Output matrix (cols × rows) in row-major orderrows: number - Number of rows in Acols: number - Number of columns in A- Returns: Float64Array (B)
Example:
constA=newFloat64Array([1,2,3,4,5,6]);// 2×3 matrixconstB=newFloat64Array(6);// 3×2 matrixaccelerate.transpose(A,B,2,3);AXPY operation: y = alpha*x + y
alpha: number - Scalar multiplierx: Float64Array - Input vectory: Float64Array - Input/output vector- Returns: Float64Array (y)
Copy vector: y = x
x: Float64Array - Input vectory: Float64Array - Output vector- Returns: Float64Array (y)
Swap two vectors: x <-> y
x: Float64Array - First vectory: Float64Array - Second vector- Returns: Float64Array (x)
L2 norm (Euclidean length): ||x||
x: Float64Array - Input vector- Returns: number
Example:
constvec=newFloat64Array([3,4]);constlength=accelerate.norm(vec);// 5Sum of absolute values: sum(|x[i]|)
x: Float64Array - Input vector- Returns: number
Index of maximum absolute value
x: Float64Array - Input vector- Returns: number (index)
Example:
constvec=newFloat64Array([1,-5,3,-2]);constidx=accelerate.maxAbsIndex(vec);// 1 (value is -5)Givens rotation: apply rotation to vectors x and y
x: Float64Array - First vectory: Float64Array - Second vectorc: number - Cosine of rotation angles: number - Sine of rotation angle- Returns: Float64Array (x)
Dot product: sum(a[i] * b[i])
a: Float64Array - First vectorb: Float64Array - Second vector (same length as a)- Returns: number
Element-wise addition: out[i] = a[i] + b[i]
a: Float64Array - First vectorb: Float64Array - Second vectorout: Float64Array - Output vector- Returns: Float64Array (out)
Element-wise subtraction: out[i] = a[i] - b[i]
a: Float64Array - First vectorb: Float64Array - Second vectorout: Float64Array - Output vector- Returns: Float64Array (out)
Element-wise multiplication: out[i] = a[i] * b[i]
a: Float64Array - First vectorb: Float64Array - Second vectorout: Float64Array - Output vector- Returns: Float64Array (out)
Element-wise division: out[i] = a[i] / b[i]
a: Float64Array - First vectorb: Float64Array - Second vectorout: Float64Array - Output vector- Returns: Float64Array (out)
Vector scaling: b = a * scalar
a: Float64Array - Input vectorscalar: number - Scalar multiplierb: Float64Array - Output vector- Returns: Float64Array (b)
Vector negation: b = -a
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Add scalar to vector: c[i] = a[i] + scalar
a: Float64Array - Input vectorscalar: number - Scalar value to addc: Float64Array - Output vector- Returns: Float64Array (c)
Multiply-add: d[i] = (a[i] * b[i]) + c[i]
a: Float64Array - First vectorb: Float64Array - Second vectorc: Float64Array - Third vectord: Float64Array - Output vector- Returns: Float64Array (d)
Example:
consta=newFloat64Array([2,3,4]);constb=newFloat64Array([5,6,7]);constc=newFloat64Array([1,1,1]);constd=newFloat64Array(3);accelerate.vma(a,b,c,d);// d = [11, 19, 29]Multiply-scalar-add: d[i] = (a[i] * b) + c[i]
a: Float64Array - Input vectorb: number - Scalar multiplierc: Float64Array - Vector to addd: Float64Array - Output vector- Returns: Float64Array (d)
Element-wise absolute value: b[i] = |a[i]|
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Element-wise square: b[i] = a[i]^2
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Element-wise square root: b[i] = sqrt(a[i])
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Normalize vector to unit length: b = a / ||a||
a: Float64Array - Input vectorb: Float64Array - Output vector (unit vector)- Returns: Float64Array (b)
Reverse vector order: b = reverse(a)
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Fill vector with scalar value
scalar: number - Value to fill withvec: Float64Array - Output vector- Returns: Float64Array (vec)
Example:
constvec=newFloat64Array(100);accelerate.vfill(3.14,vec);// All elements = 3.14Generate linear ramp: vec[i] = start + i * step
start: number - Starting valuestep: number - Step sizevec: Float64Array - Output vector- Returns: Float64Array (vec)
Example:
constvec=newFloat64Array(5);accelerate.vramp(0,2,vec);// vec = [0, 2, 4, 6, 8]Linear interpolation: c[i] = a[i] + t * (b[i] - a[i])
a: Float64Array - Start vectorb: Float64Array - End vectort: number - Interpolation parameter (0 to 1)c: Float64Array - Output vector- Returns: Float64Array (c)
Example:
conststart=newFloat64Array([0,0,0]);constend=newFloat64Array([10,20,30]);constresult=newFloat64Array(3);accelerate.vlerp(start,end,0.5,result);// result = [5, 10, 15]Clear vector (set all elements to zero)
vec: Float64Array - Vector to clear- Returns: Float64Array (vec)
Limit/saturate values to range [low, high]
a: Float64Array - Input vectorlow: number - Lower boundhigh: number - Upper boundc: Float64Array - Output vector- Returns: Float64Array (c)
Element-wise sine: b[i] = sin(a[i])
a: Float64Array - Input vector (radians)b: Float64Array - Output vector- Returns: Float64Array (b)
Element-wise cosine: b[i] = cos(a[i])
a: Float64Array - Input vector (radians)b: Float64Array - Output vector- Returns: Float64Array (b)
Element-wise tangent: b[i] = tan(a[i])
a: Float64Array - Input vector (radians)b: Float64Array - Output vector- Returns: Float64Array (b)
Example:
constangles=newFloat64Array(1000);constsines=newFloat64Array(1000);for(leti=0;i<1000;i++){angles[i]=(i/1000)*2*Math.PI;}accelerate.vsin(angles,sines);Element-wise inverse sine: b[i] = asin(a[i])
a: Float64Array - Input vector (values in [-1, 1])b: Float64Array - Output vector (radians)- Returns: Float64Array (b)
Element-wise inverse cosine: b[i] = acos(a[i])
a: Float64Array - Input vector (values in [-1, 1])b: Float64Array - Output vector (radians)- Returns: Float64Array (b)
Element-wise inverse tangent: b[i] = atan(a[i])
a: Float64Array - Input vectorb: Float64Array - Output vector (radians)- Returns: Float64Array (b)
Two-argument arctangent: out[i] = atan2(y[i], x[i])
y: Float64Array - Y coordinatesx: Float64Array - X coordinatesout: Float64Array - Output vector (radians)- Returns: Float64Array (out)
Example:
consty=newFloat64Array([1,1,-1,-1]);constx=newFloat64Array([1,-1,-1,1]);constangles=newFloat64Array(4);accelerate.vatan2(y,x,angles);// Angles in all four quadrantsElement-wise hyperbolic sine: b[i] = sinh(a[i])
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Element-wise hyperbolic cosine: b[i] = cosh(a[i])
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Element-wise hyperbolic tangent: b[i] = tanh(a[i])
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Example:
// tanh is commonly used as an activation function in neural networksconstlogits=newFloat64Array(1000);constactivations=newFloat64Array(1000);// ... fill logits ...accelerate.vtanh(logits,activations);Element-wise exponential: b[i] = exp(a[i])
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Element-wise natural logarithm: b[i] = log(a[i])
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Element-wise base-10 logarithm: b[i] = log10(a[i])
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Element-wise power: c[i] = a[i]^b[i]
a: Float64Array - Base vectorb: Float64Array - Exponent vectorc: Float64Array - Output vector- Returns: Float64Array (c)
Element-wise reciprocal: b[i] = 1 / a[i]
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Example:
constvalues=newFloat64Array([2,4,5,10]);constreciprocals=newFloat64Array(4);accelerate.vreciprocal(values,reciprocals);// [0.5, 0.25, 0.2, 0.1]Element-wise inverse square root: b[i] = 1 / sqrt(a[i])
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Example:
// Fast normalization using inverse square rootconstvec=newFloat64Array([3,4]);constsumSq=accelerate.sumOfSquares(vec);// 25constinvLen=newFloat64Array([sumSq]);constinvLenResult=newFloat64Array(1);accelerate.vrsqrt(invLen,invLenResult);// 0.2 (1/5)Element-wise ceiling: b[i] = ceil(a[i])
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Element-wise floor: b[i] = floor(a[i])
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Element-wise truncate (round toward zero): b[i] = trunc(a[i])
a: Float64Array - Input vectorb: Float64Array - Output vector- Returns: Float64Array (b)
Example:
constvalues=newFloat64Array([1.7,-1.7,2.3,-2.3]);constceiled=newFloat64Array(4);constfloored=newFloat64Array(4);consttruncated=newFloat64Array(4);accelerate.vceil(values,ceiled);// [2, -1, 3, -2]accelerate.vfloor(values,floored);// [1, -2, 2, -3]accelerate.vtrunc(values,truncated);// [1, -1, 2, -2]Copy sign: c[i] = |a[i]| * sign(b[i])
a: Float64Array - Magnitude vectorb: Float64Array - Sign vectorc: Float64Array - Output vector- Returns: Float64Array (c)
Example:
constmagnitudes=newFloat64Array([1,2,3,4]);constsigns=newFloat64Array([-1,1,-1,1]);constresult=newFloat64Array(4);accelerate.vcopysign(magnitudes,signs,result);// [-1, 2, -3, 4]Clip values to range [min, max]
a: Float64Array - Input vectorb: Float64Array - Output vectormin: number - Minimum valuemax: number - Maximum value- Returns: Float64Array (b)
Example:
constdata=newFloat64Array([-10,-5,0,5,10]);constclipped=newFloat64Array(5);accelerate.vclip(data,clipped,-3,3);// clipped = [-3, -3, 0, 3, 3]Threshold values: b[i] = a[i] if a[i] > threshold, else threshold
a: Float64Array - Input vectorb: Float64Array - Output vectorthreshold: number - Threshold value- Returns: Float64Array (b)
Sum of all elements
vec: Float64Array - Input vector- Returns: number
Mean (average) of all elements
vec: Float64Array - Input vector- Returns: number
Variance of all elements
vec: Float64Array - Input vector- Returns: number
Standard deviation of all elements
vec: Float64Array - Input vector- Returns: number
Maximum element
vec: Float64Array - Input vector- Returns: number
Minimum element
vec: Float64Array - Input vector- Returns: number
Both minimum and maximum elements
vec: Float64Array - Input vector- Returns: {min: number, max: number}
Example:
constdata=newFloat64Array([1,5,3,9,2]);conststats=accelerate.minmax(data);console.log(stats.min,stats.max);// 1, 9Root Mean Square: sqrt(sum(vec[i]^2) / n)
vec: Float64Array - Input vector- Returns: number
Sum of squares: sum(vec[i]^2)
vec: Float64Array - Input vector- Returns: number
Mean magnitude: mean(|vec[i]|)
vec: Float64Array - Input vector- Returns: number
Mean square: mean(vec[i]^2)
vec: Float64Array - Input vector- Returns: number
Maximum magnitude (absolute value)
vec: Float64Array - Input vector- Returns: number
Example:
constvec=newFloat64Array([1,-5,3,-2]);constmaxMag=accelerate.maxMagnitude(vec);// 5Minimum magnitude (absolute value)
vec: Float64Array - Input vector- Returns: number
Example:
constvec=newFloat64Array([1,-5,3,-2]);constminMag=accelerate.minMagnitude(vec);// 1Euclidean distance: sqrt(sum((a[i] - b[i])^2))
a: Float64Array - First vectorb: Float64Array - Second vector- Returns: number
Example:
constpoint1=newFloat64Array([0,0,0]);constpoint2=newFloat64Array([3,4,0]);constdistance=accelerate.euclidean(point1,point2);// 5Fast Fourier Transform (real to complex)
signal: Float64Array - Input signal (length must be power of 2)- Returns: {real: Float64Array, imag: Float64Array}
Example:
constsignal=newFloat64Array(1024);for(leti=0;i<signal.length;i++){signal[i]=Math.sin(2*Math.PI*i/signal.length);}constspectrum=accelerate.fft(signal);console.log(spectrum.real.length);// 512console.log(spectrum.imag.length);// 512Inverse Fast Fourier Transform (complex to real)
real: Float64Array - Real part of frequency domainimag: Float64Array - Imaginary part of frequency domain- Returns: Float64Array - Time domain signal
Example:
constsignal=newFloat64Array(256);// ... fill signal ...constspectrum=accelerate.fft(signal);constreconstructed=accelerate.ifft(spectrum.real,spectrum.imag);// reconstructed ≈ signal1D Convolution
signal: Float64Array - Input signalkernel: Float64Array - Convolution kernelresult: Float64Array - Output (length = signal.length - kernel.length + 1)- Returns: Float64Array (result)
Example:
constsignal=newFloat64Array([1,2,3,4,5]);constkernel=newFloat64Array([0.25,0.5,0.25]);// Moving averageconstresult=newFloat64Array(3);accelerate.conv(signal,kernel,result);Cross-correlation
a: Float64Array - First signalb: Float64Array - Second signalresult: Float64Array - Output (length = a.length + b.length - 1)- Returns: Float64Array (result)
Generate Hamming window
length: number - Window length- Returns: Float64Array - Window coefficients
Generate Hanning window
length: number - Window length- Returns: Float64Array - Window coefficients
Generate Blackman window
length: number - Window length- Returns: Float64Array - Window coefficients
Example:
constwindow=accelerate.hanning(256);constsignal=newFloat64Array(256);constwindowed=newFloat64Array(256);// Apply window to signalaccelerate.vmul(signal,window,windowed);constspectrum=accelerate.fft(windowed);Linear interpolation
x: Float64Array - X coordinates of data pointsy: Float64Array - Y coordinates of data pointsxi: Float64Array - X coordinates to interpolate atyi: Float64Array - Output interpolated Y values- Returns: Float64Array (yi)
Example:
constx=newFloat64Array([0,1,2,3]);consty=newFloat64Array([0,1,4,9]);constxi=newFloat64Array([0.5,1.5,2.5]);constyi=newFloat64Array(3);accelerate.interp1d(x,y,xi,yi);Full TypeScript definitions included:
import*asacceleratefrom'node-accelerate';constA=newFloat64Array(100*100);constB=newFloat64Array(100*100);constC=newFloat64Array(100*100);accelerate.matmul(A,B,C,100,100,100);// Neural network dense layer with activationfunctiondenseLayerWithReLU(input,weights,bias,output){constM=1,K=input.length,N=output.length;// Matrix multiplication: output = input × weightsaccelerate.matmul(input,weights,output,M,K,N);// Add biasaccelerate.vadd(output,bias,output);// ReLU activation: max(0, x)constzeros=newFloat64Array(N);accelerate.vclip(output,output,0,Infinity);returnoutput;}// Softmax activationfunctionsoftmax(logits,output){// Subtract max for numerical stabilityconstmaxVal=accelerate.max(logits);constshifted=newFloat64Array(logits.length);constnegMax=-maxVal;for(leti=0;i<logits.length;i++){shifted[i]=logits[i]+negMax;}// Compute expaccelerate.vexp(shifted,output);// Normalizeconstsum=accelerate.sum(output);accelerate.vscale(output,1.0/sum,output);returnoutput;}// Apply windowed FFT for spectral analysisfunctionspectralAnalysis(audioBuffer,windowSize=2048){constwindow=accelerate.hanning(windowSize);constwindowed=newFloat64Array(windowSize);// Apply windowaccelerate.vmul(audioBuffer,window,windowed);// Compute FFTconstspectrum=accelerate.fft(windowed);// Compute magnitude spectrumconstmagnitudes=newFloat64Array(spectrum.real.length);for(leti=0;i<magnitudes.length;i++){magnitudes[i]=Math.sqrt(spectrum.real[i]**2+spectrum.imag[i]**2);}// Convert to dBconstdB=newFloat64Array(magnitudes.length);accelerate.vlog10(magnitudes,dB);accelerate.vscale(dB,20,dB);returndB;}// Low-pass filter using convolutionfunctionlowPassFilter(signal,cutoffFreq,sampleRate){// Design simple FIR filter kernelconstkernelSize=51;constkernel=newFloat64Array(kernelSize);// Sinc function kernelconstfc=cutoffFreq/sampleRate;for(leti=0;i<kernelSize;i++){constx=i-kernelSize/2;if(x===0){kernel[i]=2*fc;}else{kernel[i]=Math.sin(2*Math.PI*fc*x)/(Math.PI*x);}}// Apply Hamming window to kernelconstwindow=accelerate.hamming(kernelSize);accelerate.vmul(kernel,window,kernel);// Normalizeconstsum=accelerate.sum(kernel);accelerate.vscale(kernel,1.0/sum,kernel);// Convolveconstfiltered=newFloat64Array(signal.length-kernelSize+1);accelerate.conv(signal,kernel,filtered);returnfiltered;}// Numerical integration using trapezoidal rulefunctiontrapezoidalIntegration(f,a,b,n){consth=(b-a)/n;constx=newFloat64Array(n+1);consty=newFloat64Array(n+1);// Generate pointsfor(leti=0;i<=n;i++){x[i]=a+i*h;y[i]=f(x[i]);}// Trapezoidal rule: h * (y[0]/2 + y[1] + ... + y[n-1] + y[n]/2)constsum=accelerate.sum(y);returnh*(sum-(y[0]+y[n])/2);}// Compute correlation coefficientfunctioncorrelationCoefficient(x,y){constn=x.length;// Compute meansconstmeanX=accelerate.mean(x);constmeanY=accelerate.mean(y);// Center the dataconstxCentered=newFloat64Array(n);constyCentered=newFloat64Array(n);for(leti=0;i<n;i++){xCentered[i]=x[i]-meanX;yCentered[i]=y[i]-meanY;}// Compute correlationconstnumerator=accelerate.dot(xCentered,yCentered);constdenomX=Math.sqrt(accelerate.sumOfSquares(xCentered));constdenomY=Math.sqrt(accelerate.sumOfSquares(yCentered));returnnumerator/(denomX*denomY);}// Polynomial evaluation using Horner's method (vectorized)functionpolyval(coefficients,x,result){constn=x.length;constdegree=coefficients.length-1;// Initialize with highest degree coefficientfor(leti=0;i<n;i++){result[i]=coefficients[degree];}// Horner's method: result = result * x + coefffor(leti=degree-1;i>=0;i--){accelerate.vmul(result,x,result);constcoeff=newFloat64Array(n);coeff.fill(coefficients[i]);accelerate.vadd(result,coeff,result);}returnresult;}// Compute z-scores (standardization)functionzScore(data,output){constmean=accelerate.mean(data);conststd=accelerate.stddev(data);// z = (x - mean) / stdfor(leti=0;i<data.length;i++){output[i]=data[i]-mean;}accelerate.vscale(output,1.0/std,output);returnoutput;}// Moving average filterfunctionmovingAverage(data,windowSize){constkernel=newFloat64Array(windowSize);kernel.fill(1.0/windowSize);constresult=newFloat64Array(data.length-windowSize+1);accelerate.conv(data,kernel,result);returnresult;}// Outlier detection using IQR methodfunctiondetectOutliers(data){constsorted=newFloat64Array(data);// Note: You'd need to implement sorting or use JS sortconstq1Index=Math.floor(data.length*0.25);constq3Index=Math.floor(data.length*0.75);constq1=sorted[q1Index];constq3=sorted[q3Index];constiqr=q3-q1;constlowerBound=q1-1.5*iqr;constupperBound=q3+1.5*iqr;constoutliers=[];for(leti=0;i<data.length;i++){if(data[i]<lowerBound||data[i]>upperBound){outliers.push({index: i,value: data[i]});}}returnoutliers;}// Gaussian blur (separable convolution)functiongaussianBlur(image,width,height,sigma){// Generate 1D Gaussian kernelconstkernelSize=Math.ceil(sigma*6)|1;// Ensure oddconstkernel=newFloat64Array(kernelSize);constcenter=Math.floor(kernelSize/2);for(leti=0;i<kernelSize;i++){constx=i-center;kernel[i]=Math.exp(-(x*x)/(2*sigma*sigma));}// Normalizeconstsum=accelerate.sum(kernel);accelerate.vscale(kernel,1.0/sum,kernel);// Horizontal passconsttemp=newFloat64Array(width*height);for(lety=0;y<height;y++){constrow=image.subarray(y*width,(y+1)*width);constoutRow=temp.subarray(y*width,(y+1)*width);// Convolve row (simplified - needs padding)accelerate.conv(row,kernel,outRow);}// Vertical pass (similar logic)// ...returntemp;}// Edge detection using Sobel operatorfunctionsobelEdgeDetection(image,width,height){constsobelX=newFloat64Array([-1,0,1,-2,0,2,-1,0,1]);constsobelY=newFloat64Array([-1,-2,-1,0,0,0,1,2,1]);constgradX=newFloat64Array(width*height);constgradY=newFloat64Array(width*height);constmagnitude=newFloat64Array(width*height);// Apply Sobel kernels (simplified)// ... convolution logic ...// Compute gradient magnitudeconstgradXSq=newFloat64Array(width*height);constgradYSq=newFloat64Array(width*height);accelerate.vsquare(gradX,gradXSq);accelerate.vsquare(gradY,gradYSq);accelerate.vadd(gradXSq,gradYSq,magnitude);accelerate.vsqrt(magnitude,magnitude);returnmagnitude;}// Calculate returns and volatilityfunctioncalculateReturns(prices){constreturns=newFloat64Array(prices.length-1);for(leti=1;i<prices.length;i++){returns[i-1]=(prices[i]-prices[i-1])/prices[i-1];}constmeanReturn=accelerate.mean(returns);constvolatility=accelerate.stddev(returns);return{ returns, meanReturn, volatility };}// Exponential moving averagefunctionexponentialMovingAverage(data,alpha){constema=newFloat64Array(data.length);ema[0]=data[0];for(leti=1;i<data.length;i++){ema[i]=alpha*data[i]+(1-alpha)*ema[i-1];}returnema;}// Bollinger BandsfunctionbollingerBands(prices,period,numStdDev){constma=movingAverage(prices,period);constupper=newFloat64Array(ma.length);constlower=newFloat64Array(ma.length);for(leti=0;i<ma.length;i++){constwindow=prices.subarray(i,i+period);conststd=accelerate.stddev(window);upper[i]=ma[i]+numStdDev*std;lower[i]=ma[i]-numStdDev*std;}return{middle: ma, upper, lower };}Run the included benchmarks:
npm run benchmarkRun tests:
npm testCompare with pure JavaScript:
npm run compare- Reuse buffers - Allocate Float64Arrays once and reuse them
- Batch operations - Process large arrays instead of many small ones
- Use appropriate sizes - Accelerate shines with larger data (1000+ elements)
- Profile your code - Not all operations benefit equally
- Use windows for FFT - Apply Hanning/Hamming windows before FFT for better spectral analysis
- Leverage vectorized trig - Use vsin/vcos/vtan instead of loops with Math.sin/cos/tan
- Chain operations - Minimize intermediate allocations
matmul(A, B, C, M, K, N)- Matrix multiplication (double precision)matmulFloat(A, B, C, M, K, N)- Matrix multiplication (single precision)matvec(A, x, y, M, N)- Matrix-vector multiplicationtranspose(A, B, rows, cols)- Matrix transposeaxpy(alpha, x, y)- AXPY operation (y = alpha*x + y)copy(x, y)- Vector copyswap(x, y)- Vector swapnorm(x)- L2 norm (Euclidean length)abssum(x)- Sum of absolute valuesmaxAbsIndex(x)- Index of maximum absolute valuerot(x, y, c, s)- Givens rotation
dot(a, b)- Dot productvadd(a, b, out)- Element-wise additionvsub(a, b, out)- Element-wise subtractionvmul(a, b, out)- Element-wise multiplicationvdiv(a, b, out)- Element-wise divisionvscale(a, scalar, b)- Scalar multiplicationvneg(a, b)- NegationvaddScalar(a, scalar, c)- Add scalar to vectorvma(a, b, c, d)- Multiply-add: d = (a*b) + cvmsa(a, b, c, d)- Multiply-scalar-add: d = (a*b) + c
vabs(a, b)- Absolute valuevsquare(a, b)- Squarevsqrt(a, b)- Square rootnormalize(a, b)- Normalize to unit lengthvreverse(a, b)- Reverse ordervfill(scalar, vec)- Fill with scalarvramp(start, step, vec)- Generate linear rampvlerp(a, b, t, c)- Linear interpolationvclear(vec)- Clear (set to zero)vlimit(a, low, high, c)- Limit/saturate values
vsin(a, b)- Sinevcos(a, b)- Cosinevtan(a, b)- Tangentvasin(a, b)- Inverse sinevacos(a, b)- Inverse cosinevatan(a, b)- Inverse tangentvatan2(y, x, out)- Two-argument arctangent
vsinh(a, b)- Hyperbolic sinevcosh(a, b)- Hyperbolic cosinevtanh(a, b)- Hyperbolic tangent
vexp(a, b)- Natural exponentialvlog(a, b)- Natural logarithmvlog10(a, b)- Base-10 logarithmvpow(a, b, c)- Power (c = a^b)vreciprocal(a, b)- Reciprocal (1/x)vrsqrt(a, b)- Inverse square root (1/sqrt(x))
vceil(a, b)- Ceilingvfloor(a, b)- Floorvtrunc(a, b)- Truncate (round toward zero)vcopysign(a, b, c)- Copy sign
vclip(a, b, min, max)- Clip to rangevthreshold(a, b, threshold)- Apply threshold
sum(vec)- Sum of elementsmean(vec)- Mean (average)variance(vec)- Variancestddev(vec)- Standard deviationmax(vec)- Maximum valuemin(vec)- Minimum valueminmax(vec)- Both min and maxrms(vec)- Root mean squaresumOfSquares(vec)- Sum of squaresmeanMagnitude(vec)- Mean of absolute valuesmeanSquare(vec)- Mean of squaresmaxMagnitude(vec)- Maximum magnitudeminMagnitude(vec)- Minimum magnitude
euclidean(a, b)- Euclidean distance
fft(signal)- Fast Fourier Transformifft(real, imag)- Inverse FFTconv(signal, kernel, result)- Convolutionxcorr(a, b, result)- Cross-correlation
hamming(length)- Hamming windowhanning(length)- Hanning windowblackman(length)- Blackman window
interp1d(x, y, xi, yi)- Linear interpolation
Total: 80+ functions - All hardware-accelerated via Apple's Accelerate framework
- macOS only - Requires Apple's Accelerate framework
- Float64Array only - Currently supports double precision only
- Row-major order - Matrices must be in row-major format
- FFT size - Must be power of 2
Contributions welcome! See CONTRIBUTING.md for guidelines.
MIT © Jessica Mulein
Built on Apple's Accelerate framework. Inspired by the need for high-performance numerical computing in Node.js on Apple Silicon.
Make sure you installed it:
npm install @digitaldefiance/node-accelerateRebuild the addon:
npm rebuild @digitaldefiance/node-accelerateThis package only works on macOS because it uses Apple's Accelerate framework. It cannot run on Linux or Windows.
Install Xcode Command Line Tools:
xcode-select --installnode-accelerate supports:
- ARM64 (Apple Silicon: M1/M2/M3/M4)
- x64 (Intel Macs)
If you're on an older Mac with a different architecture, this package won't work.
- Make sure you're using large arrays (1000+ elements)
- Reuse buffers instead of allocating new ones
- Run
npm run compareto see actual speedups on your machine - Check that you're not running in a VM or emulator
Made with ❤️ for Apple Silicon