numz 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/.vscode/extensions.json +4 -0
- package/docs/.vscode/launch.json +11 -0
- package/docs/README.md +49 -0
- package/docs/astro.config.mjs +64 -0
- package/docs/package-lock.json +7592 -0
- package/docs/package.json +19 -0
- package/docs/public/favicon.svg +1 -0
- package/docs/src/assets/houston.webp +0 -0
- package/docs/src/content/docs/about.md +11 -0
- package/docs/src/content/docs/guides/example.md +11 -0
- package/docs/src/content/docs/index.mdx +40 -0
- package/docs/src/content/docs/philosophy.md +15 -0
- package/docs/src/content/docs/reference/complex/complex.mdx +66 -0
- package/docs/src/content/docs/reference/functions/arithmetic.md +14 -0
- package/docs/src/content/docs/reference/functions/mapfun.md +81 -0
- package/docs/src/content/docs/reference/functions/ufunc.md +41 -0
- package/docs/src/content/docs/reference/functions/utils.md +16 -0
- package/docs/src/content/docs/reference/matrix/matrix.mdx +97 -0
- package/docs/src/content/docs/reference/signal/functions/periodic/pulse-train.md +6 -0
- package/docs/src/content/docs/reference/signal/functions/periodic/pwm.md +6 -0
- package/docs/src/content/docs/reference/signal/functions/periodic/sawtooth-train.md +6 -0
- package/docs/src/content/docs/reference/signal/functions/periodic/sinusoid.md +6 -0
- package/docs/src/content/docs/reference/signal/functions/periodic/square.md +6 -0
- package/docs/src/content/docs/reference/signal/functions/periodic/triangle.md +6 -0
- package/docs/src/content/docs/reference/signal/functions/pulse/dirac.md +12 -0
- package/docs/src/content/docs/reference/signal/functions/pulse/noise.md +12 -0
- package/docs/src/content/docs/reference/signal/functions/pulse/rampe.md +12 -0
- package/docs/src/content/docs/reference/signal/functions/pulse/rect.md +12 -0
- package/docs/src/content/docs/reference/signal/functions/pulse/signum.md +12 -0
- package/docs/src/content/docs/reference/signal/functions/pulse/sinc.md +12 -0
- package/docs/src/content/docs/reference/signal/functions/pulse/trapezoid.md +12 -0
- package/docs/src/content/docs/reference/signal/functions/pulse/tri.md +12 -0
- package/docs/src/content/docs/reference/signal/functions/sequences/arange.md +21 -0
- package/docs/src/content/docs/reference/signal/functions/sequences/geomspace.md +21 -0
- package/docs/src/content/docs/reference/signal/functions/sequences/linspace.md +16 -0
- package/docs/src/content/docs/reference/signal/functions/sequences/logspace.md +20 -0
- package/docs/src/content/docs/reference/signal/functions/sequences/nums.md +17 -0
- package/docs/src/content/docs/reference/signal/functions/sequences/ones.md +19 -0
- package/docs/src/content/docs/reference/signal/functions/sequences/zeros.md +20 -0
- package/docs/src/content/docs/reference/stats/accum/accum-max.md +4 -0
- package/docs/src/content/docs/reference/stats/accum/accum-min.md +4 -0
- package/docs/src/content/docs/reference/stats/accum/accum-prod.md +4 -0
- package/docs/src/content/docs/reference/stats/accum/accum-sum.md +4 -0
- package/docs/src/content/docs/reference/stats/averages/contraharmonic-mean.md +4 -0
- package/docs/src/content/docs/reference/stats/averages/geo_mean.md +6 -0
- package/docs/src/content/docs/reference/stats/averages/harmonic_mean.md +4 -0
- package/docs/src/content/docs/reference/stats/averages/iq-mean.md +4 -0
- package/docs/src/content/docs/reference/stats/averages/mean.md +6 -0
- package/docs/src/content/docs/reference/stats/averages/midhinge.md +4 -0
- package/docs/src/content/docs/reference/stats/averages/midrange.md +4 -0
- package/docs/src/content/docs/reference/stats/averages/power_mean.md +4 -0
- package/docs/src/content/docs/reference/stats/averages/rms.md +12 -0
- package/docs/src/content/docs/reference/stats/averages/trimmed_mean.md +4 -0
- package/docs/src/content/docs/reference/stats/averages/weighted_mean.md +4 -0
- package/docs/src/content/docs/reference/stats/averages/winsorized_mean.md +4 -0
- package/docs/src/content.config.ts +7 -0
- package/docs/src/pages/a.astro +0 -0
- package/docs/src/styles/custom.css +21 -0
- package/docs/tsconfig.json +5 -0
- package/package.json +2 -2
- package/src/signal/conv/conv.js +43 -0
- package/src/signal/conv/conv2.js +71 -0
- package/src/signal/conv/index.js +2 -0
- package/src/signal/fft/fft.js +47 -0
- package/src/signal/fft/ifft.js +16 -0
- package/src/signal/fft/index.js +2 -52
- package/src/signal/fft/utils/index.js +1 -19
- package/src/signal/functions/index.js +1 -1
- package/src/signal/functions/sequence/index.js +13 -3
- package/src/signal/index.js +1 -1
- package/src/stats/average/index.js +2 -2
- package/test/index.js +39 -0
- package/test/index.py +14 -0
- package/src/signal/fft/fft1d/index.js +0 -18
- package/src/signal/fft/fftnd/index.js +0 -27
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: nums
|
|
3
|
+
description: nums
|
|
4
|
+
sidebar :
|
|
5
|
+
order: 2
|
|
6
|
+
---
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
## Signature
|
|
10
|
+
```ts
|
|
11
|
+
nums(num : number, n : number) : number[]
|
|
12
|
+
```
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
const z = nums(1.5, 10) // [1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5]
|
|
17
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: zeros
|
|
3
|
+
description: zeros
|
|
4
|
+
sidebar:
|
|
5
|
+
order : 0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Defintion
|
|
9
|
+
|
|
10
|
+
## Signature
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
zeros(n : number) : []number
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
const z = zeros(10) // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
20
|
+
```
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { defineCollection } from 'astro:content';
|
|
2
|
+
import { docsLoader } from '@astrojs/starlight/loaders';
|
|
3
|
+
import { docsSchema } from '@astrojs/starlight/schema';
|
|
4
|
+
|
|
5
|
+
export const collections = {
|
|
6
|
+
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
|
|
7
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--sl-content-width: 50rem;
|
|
3
|
+
--sl-text-5xl: 3.5rem;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
h1{
|
|
7
|
+
color : darkblue;
|
|
8
|
+
/* text-decoration: 2px underline blueviolet;
|
|
9
|
+
text-decoration-skip-ink: auto; */
|
|
10
|
+
/* border-bottom: 1px red solid; */
|
|
11
|
+
}
|
|
12
|
+
p a{
|
|
13
|
+
color: blueviolet;
|
|
14
|
+
text-decoration: none;
|
|
15
|
+
&:hover{
|
|
16
|
+
text-decoration: underline;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/* strong{
|
|
20
|
+
color: blueviolet;
|
|
21
|
+
} */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "numz",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "scientific computing with zikojs",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -29,6 +29,6 @@
|
|
|
29
29
|
"rollup": "^4.24.0"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"ziko": "^0.
|
|
32
|
+
"ziko": "^0.57.0"
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Complex } from 'ziko/math/complex';
|
|
2
|
+
import { add, mul} from 'ziko/math/functions'
|
|
3
|
+
|
|
4
|
+
// const nextPow2 = n => 1 << Math.ceil(Math.log2(n));
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export function conv(signal, kernel, mode = 'full') {
|
|
8
|
+
const N = signal.length;
|
|
9
|
+
const M = kernel.length;
|
|
10
|
+
if(signal.some(n => n?.isComplex?.()) || kernel.some(n => n?.isComplex?.())){
|
|
11
|
+
signal = new Complex(signal, 0);
|
|
12
|
+
kernel = new Complex(kernel, 0);
|
|
13
|
+
}
|
|
14
|
+
let outLength;
|
|
15
|
+
let startIdx;
|
|
16
|
+
switch(mode){
|
|
17
|
+
case 'full' : {
|
|
18
|
+
outLength = N + M - 1;
|
|
19
|
+
startIdx = 0;
|
|
20
|
+
}; break;
|
|
21
|
+
case 'same' : {
|
|
22
|
+
outLength = N;
|
|
23
|
+
startIdx = Math.floor((M - 1) / 2);
|
|
24
|
+
}; break;
|
|
25
|
+
case 'valid' : {
|
|
26
|
+
outLength = Math.max(N - M + 1, 0);
|
|
27
|
+
startIdx = M - 1;
|
|
28
|
+
}; break;
|
|
29
|
+
default : throw new Error(`Invalid mode: ${mode}. Must be 'full', 'same', or 'valid'`);
|
|
30
|
+
}
|
|
31
|
+
const out = new Array(outLength);
|
|
32
|
+
for (let n = 0; n < outLength; n++) {
|
|
33
|
+
let sum = new Complex(0, 0);
|
|
34
|
+
const actualN = n + startIdx;
|
|
35
|
+
for (let k = 0; k < M; k++) {
|
|
36
|
+
const idx = actualN - k;
|
|
37
|
+
if (idx >= 0 && idx < N)
|
|
38
|
+
sum = add(mul(signal[idx], kernel[k]))
|
|
39
|
+
}
|
|
40
|
+
out[n] = sum;
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Complex } from 'ziko/math/complex';
|
|
2
|
+
import { add, mul} from 'ziko/math/functions'
|
|
3
|
+
export function conv2(signal, kernel, mode = 'full', boundary = 'fill', fillValue = 0) {
|
|
4
|
+
const isMatix = signal?.isMatix?.() || kernel?.isMatix?.();
|
|
5
|
+
const signalRows = signal.length;
|
|
6
|
+
const signalCols = signal[0].length;
|
|
7
|
+
const kernelRows = kernel.length;
|
|
8
|
+
const kernelCols = kernel[0].length;
|
|
9
|
+
|
|
10
|
+
const flippedKernel = kernel.map(row => [...row].reverse()).reverse();
|
|
11
|
+
|
|
12
|
+
// Determine output size
|
|
13
|
+
let outRows, outCols;
|
|
14
|
+
switch(mode){
|
|
15
|
+
case 'full':{
|
|
16
|
+
outRows = signalRows + kernelRows - 1;
|
|
17
|
+
outCols = signalCols + kernelCols - 1;
|
|
18
|
+
}; break;
|
|
19
|
+
case 'same':{
|
|
20
|
+
outRows = signalRows;
|
|
21
|
+
outCols = signalCols;
|
|
22
|
+
}; break;
|
|
23
|
+
case 'valid':{
|
|
24
|
+
outRows = signalRows - kernelRows + 1;
|
|
25
|
+
outCols = signalCols - kernelCols + 1;
|
|
26
|
+
}; break;
|
|
27
|
+
default: throw new Error("mode must be 'full', 'same', or 'valid'");
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
// Initialize output
|
|
31
|
+
const output = Array.from({ length: outRows }, () => Array(outCols).fill(0));
|
|
32
|
+
|
|
33
|
+
// Helper to get signal value considering boundary
|
|
34
|
+
function getSignalValue(i, j) {
|
|
35
|
+
if (i < 0 || i >= signalRows || j < 0 || j >= signalCols) {
|
|
36
|
+
if (boundary === 'fill') return fillValue;
|
|
37
|
+
if (boundary === 'wrap') return signal[(i + signalRows) % signalRows][(j + signalCols) % signalCols];
|
|
38
|
+
if (boundary === 'symm') {
|
|
39
|
+
const ii = i < 0 ? -i - 1 : i >= signalRows ? 2*signalRows - i - 1 : i;
|
|
40
|
+
const jj = j < 0 ? -j - 1 : j >= signalCols ? 2*signalCols - j - 1 : j;
|
|
41
|
+
return signal[ii][jj];
|
|
42
|
+
}
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
return signal[i][j];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Convolution
|
|
49
|
+
for (let i = 0; i < outRows; i++) {
|
|
50
|
+
for (let j = 0; j < outCols; j++) {
|
|
51
|
+
let sum = 0;
|
|
52
|
+
for (let m = 0; m < kernelRows; m++) {
|
|
53
|
+
for (let n = 0; n < kernelCols; n++) {
|
|
54
|
+
const ii = i + m - Math.floor(kernelRows / 2);
|
|
55
|
+
const jj = j + n - Math.floor(kernelCols / 2);
|
|
56
|
+
sum += flippedKernel[m][n] * getSignalValue(ii, jj);
|
|
57
|
+
sum = add(
|
|
58
|
+
mul(
|
|
59
|
+
flippedKernel[m][n],
|
|
60
|
+
getSignalValue(ii, jj)
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
output[i][j] = sum;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return output;
|
|
70
|
+
}
|
|
71
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Complex } from 'ziko/math/complex'
|
|
2
|
+
import { isPow2 } from './utils/index.js';
|
|
3
|
+
|
|
4
|
+
export function dft(arr) {
|
|
5
|
+
const N = arr.length;
|
|
6
|
+
const out = new Array(N);
|
|
7
|
+
|
|
8
|
+
for (let k = 0; k < N; k++) {
|
|
9
|
+
let sum = new Complex(0, 0);
|
|
10
|
+
for (let n = 0; n < N; n++) {
|
|
11
|
+
const W = Complex.twiddle(k * n, N);
|
|
12
|
+
sum = sum.add(W.mul(arr[n]));
|
|
13
|
+
}
|
|
14
|
+
out[k] = sum;
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function fft(arr) {
|
|
20
|
+
const N = arr.length;
|
|
21
|
+
|
|
22
|
+
// fallback for non power-of-two
|
|
23
|
+
if (!isPow2(N)) {
|
|
24
|
+
return dft(arr);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (N === 1) return [arr[0]];
|
|
28
|
+
|
|
29
|
+
const even = new Array(N / 2);
|
|
30
|
+
const odd = new Array(N / 2);
|
|
31
|
+
|
|
32
|
+
for (let i = 0; i < N / 2; i++) {
|
|
33
|
+
even[i] = arr[2*i];
|
|
34
|
+
odd[i] = arr[2*i+1];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const Fe = fft(even);
|
|
38
|
+
const Fo = fft(odd);
|
|
39
|
+
|
|
40
|
+
const out = new Array(N);
|
|
41
|
+
for (let k = 0; k < N / 2; k++) {
|
|
42
|
+
const t = Complex.twiddle(k, N).mul(Fo[k]);
|
|
43
|
+
out[k] = Fe[k].add(t);
|
|
44
|
+
out[k+N/2] = Fe[k].sub(t);
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Complex } from 'ziko/math/complex';
|
|
2
|
+
import { fft, dft } from './fft.js';
|
|
3
|
+
import { isPow2 } from './utils/index.js';
|
|
4
|
+
|
|
5
|
+
export function ifft(arr) {
|
|
6
|
+
const N = arr.length;
|
|
7
|
+
|
|
8
|
+
// Step 1: conjugate input
|
|
9
|
+
const conjugated = arr.map(n => new Complex(n, 0).conj)
|
|
10
|
+
|
|
11
|
+
// Step 2: compute FFT (or DFT if not power-of-2)
|
|
12
|
+
const y = isPow2(N) ? fft(conjugated) : dft(conjugated);
|
|
13
|
+
|
|
14
|
+
// Step 3: conjugate output and normalize
|
|
15
|
+
return y.map(c => new Complex(c.a / N, -c.b / N));
|
|
16
|
+
}
|
package/src/signal/fft/index.js
CHANGED
|
@@ -1,52 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export function fft1d(arr) {
|
|
4
|
-
const N = arr.length;
|
|
5
|
-
if (N === 1) return [arr[0]];
|
|
6
|
-
|
|
7
|
-
const even = fft1d(arr.filter((_, i) => i % 2 === 0));
|
|
8
|
-
const odd = fft1d(arr.filter((_, i) => i % 2 === 1));
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const out = new Array(N);
|
|
13
|
-
for (let k = 0; k < N/2; k++) {
|
|
14
|
-
const t = Complex.Twidlle(N, k).mul(odd[k]);
|
|
15
|
-
out[k] = add(even[k], t)
|
|
16
|
-
out[k + N/2] = sub(even[k], t)
|
|
17
|
-
}
|
|
18
|
-
return out;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function fftnd(data) {
|
|
22
|
-
if (data instanceof Matrix) data = data.toComplex();
|
|
23
|
-
|
|
24
|
-
if (Array.isArray(data) && !Array.isArray(data[0])) {
|
|
25
|
-
return fft1d(data);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (data instanceof Matrix) {
|
|
29
|
-
const rows = data.rows;
|
|
30
|
-
const cols = data.cols;
|
|
31
|
-
|
|
32
|
-
// FFT along rows
|
|
33
|
-
let rowFFT = new Matrix(rows, cols, []);
|
|
34
|
-
for (let i = 0; i < rows; i++) {
|
|
35
|
-
rowFFT.arr[i] = fft1d(data.arr[i]);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
let colFFT = new Matrix(cols, rows, []);
|
|
39
|
-
const rowFFT_T = rowFFT.T;
|
|
40
|
-
for (let i = 0; i < cols; i++) {
|
|
41
|
-
colFFT.arr[i] = fft1d(rowFFT_T.arr[i]);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return colFFT.T;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (Array.isArray(data)) {
|
|
48
|
-
return data.map(fftnd);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
throw new Error("Invalid data type for FFT");
|
|
52
|
-
}
|
|
1
|
+
export * from './fft.js';
|
|
2
|
+
export * from './ifft.js'
|
|
@@ -1,19 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// export function twiddle(N, k) {
|
|
3
|
-
// const angle = -2 * Math.PI * k / N;
|
|
4
|
-
// return new Complex(Math.cos(angle), Math.sin(angle));
|
|
5
|
-
// }
|
|
6
|
-
|
|
7
|
-
// function normalizeComplexND(data) {
|
|
8
|
-
// if (data instanceof Matrix) {
|
|
9
|
-
// return new Matrix(
|
|
10
|
-
// data.rows,
|
|
11
|
-
// data.cols,
|
|
12
|
-
// data.arr.flat(1).map(C)
|
|
13
|
-
// );
|
|
14
|
-
// } else if (Array.isArray(data)) {
|
|
15
|
-
// return data.map(normalizeComplexND);
|
|
16
|
-
// } else {
|
|
17
|
-
// return C(data);
|
|
18
|
-
// }
|
|
19
|
-
// }
|
|
1
|
+
export const isPow2 = n => (n & (n - 1)) === 0;
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import { mapfun, nthr, pow } from "ziko/math/functions";
|
|
2
|
+
import { Matrix } from 'ziko/math/matrix'
|
|
2
3
|
|
|
3
|
-
export const zeros = n =>
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
export const zeros = (n, m, d) => {
|
|
5
|
+
if(m) return Matrix.zeros(n, m);
|
|
6
|
+
return new Array(n).fill(0)
|
|
7
|
+
}
|
|
8
|
+
export const ones = (n, m) => {
|
|
9
|
+
if(m) return Matrix.ones(n, m);
|
|
10
|
+
return new Array(n).fill(1)
|
|
11
|
+
};
|
|
12
|
+
export const nums = (num, n, m, d) => {
|
|
13
|
+
if(m) return Matrix.nums(n, m);
|
|
14
|
+
return new Array(n).fill(num)
|
|
15
|
+
};
|
|
6
16
|
|
|
7
17
|
|
|
8
18
|
export const arange = (a, b, step, include = false) => {
|
package/src/signal/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from './functions/index.js'
|
|
2
|
-
|
|
2
|
+
export * from './fft/index.js'
|
|
@@ -55,8 +55,8 @@ export const midhinge = (...x) =>{
|
|
|
55
55
|
return (q1 + q3) / 2;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
export const
|
|
58
|
+
// interquartile_mean
|
|
59
|
+
export const iq_mean = (...x) =>{
|
|
60
60
|
let a = x.sort((a,b)=>a-b);
|
|
61
61
|
let q1 = a[Math.floor((a.length - 1) * 0.25)];
|
|
62
62
|
let q3 = a[Math.floor((a.length - 1) * 0.75)];
|
package/test/index.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { fft, ifft } from "../src/signal/fft/index.js";
|
|
2
|
+
import { conv, conv2 } from '../src/signal/conv/index.js'
|
|
3
|
+
import { Complex } from "ziko/math/complex";
|
|
4
|
+
// import { cos } from 'ziko/math/functions'
|
|
5
|
+
|
|
6
|
+
// const x = Array.from({ length: 100 }, (_, j)=> j/10)
|
|
7
|
+
// const y = cos(x)
|
|
8
|
+
|
|
9
|
+
// const ff = fft(x)
|
|
10
|
+
// // const ff = fft([1,2,3])
|
|
11
|
+
// // console.log(ff)
|
|
12
|
+
|
|
13
|
+
// // console.log(ifft(ff))
|
|
14
|
+
const signal = [1, 2, 3, 4, 5];
|
|
15
|
+
let kernel = [1, 0.5];
|
|
16
|
+
// kernel = [1, new Complex(0, 0.5)];
|
|
17
|
+
const result = conv(signal, kernel);
|
|
18
|
+
console.log(
|
|
19
|
+
result
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
// console.log(ff)
|
|
23
|
+
// console.log(ifft(ff).map(n=>+ n.a.toFixed(7)))
|
|
24
|
+
// console.log(x)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
// Example usage:
|
|
28
|
+
const image = [
|
|
29
|
+
[1, 2, 3],
|
|
30
|
+
[4, 5, 6],
|
|
31
|
+
[7, 8, 9]
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const filter = [
|
|
35
|
+
[1, 0],
|
|
36
|
+
[0, 1]
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
console.log(conv2(image, filter, 'full', 'fill'));
|
package/test/index.py
ADDED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { twiddle } from "../utils/index.js";
|
|
2
|
-
export function fft1d(arr) {
|
|
3
|
-
const N = arr.length;
|
|
4
|
-
if (N === 1) return [arr[0]];
|
|
5
|
-
|
|
6
|
-
// Split even/odd
|
|
7
|
-
const even = fft1d(arr.filter((_, i) => i % 2 === 0));
|
|
8
|
-
const odd = fft1d(arr.filter((_, i) => i % 2 === 1));
|
|
9
|
-
|
|
10
|
-
const out = new Array(N);
|
|
11
|
-
for (let k = 0; k < N/2; k++) {
|
|
12
|
-
const w = twiddle(N, k);
|
|
13
|
-
const t = w.mul(odd[k]);
|
|
14
|
-
out[k] = even[k].add(t);
|
|
15
|
-
out[k + N/2] = even[k].sub(t);
|
|
16
|
-
}
|
|
17
|
-
return out;
|
|
18
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { normalizeComplexND } from '../utils/index.js'
|
|
2
|
-
import { fft1d } from '../fft1d/index.js';
|
|
3
|
-
function fftND(arr) {
|
|
4
|
-
arr = normalizeComplexND(arr);
|
|
5
|
-
|
|
6
|
-
// Base case: 1-D
|
|
7
|
-
if (!Array.isArray(arr[0]))
|
|
8
|
-
return fft1d(arr);
|
|
9
|
-
|
|
10
|
-
const transformed = arr.map(sub => fftND(sub));
|
|
11
|
-
|
|
12
|
-
const rows = transformed.length;
|
|
13
|
-
const cols = transformed[0].length;
|
|
14
|
-
|
|
15
|
-
const colsData = Array.from({ length: cols }, (_, c) =>
|
|
16
|
-
Array.from({ length: rows }, (_, r) => transformed[r][c])
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
const colsTransformed = colsData.map(col => fft1d(col));
|
|
20
|
-
|
|
21
|
-
// Transpose back
|
|
22
|
-
const out = Array.from({ length: rows }, (_, r) =>
|
|
23
|
-
Array.from({ length: cols }, (_, c) => colsTransformed[c][r])
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
return out;
|
|
27
|
-
}
|