Skip to content

Commit bc3b79f

Browse files
gunjjoshikgryte
andauthored
feat: add fft/base/fftpack/cosqi
PR-URL: #12881 Co-authored-by: Athan Reines <kgryte@gmail.com> Reviewed-by: Athan Reines <kgryte@gmail.com> Signed-off-by: Athan Reines <kgryte@gmail.com> Closes: stdlib-js/metr-issue-tracker#811 Ref: #4121
1 parent 900a4e2 commit bc3b79f

15 files changed

Lines changed: 1607 additions & 0 deletions

File tree

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2026 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# cosqi
22+
23+
> Initialize a workspace array for performing a quarter-wave cosine transform.
24+
25+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
26+
27+
<section class="intro">
28+
29+
</section>
30+
31+
<!-- /.intro -->
32+
33+
<!-- Package usage documentation. -->
34+
35+
<section class="usage">
36+
37+
## Usage
38+
39+
```javascript
40+
var cosqi = require( '@stdlib/fft/base/fftpack/cosqi' );
41+
```
42+
43+
#### cosqi( N, workspace, strideW, offsetW )
44+
45+
Initializes a workspace array for performing a quarter-wave cosine transform.
46+
47+
```javascript
48+
var Float64Array = require( '@stdlib/array/float64' );
49+
50+
var N = 8;
51+
var workspace = new Float64Array( ( 3*N ) + 34 );
52+
53+
var out = cosqi( N, workspace, 1, 0 );
54+
// returns <Float64Array>
55+
56+
var bool = ( out === workspace );
57+
// returns true
58+
59+
var cosineTable = workspace.slice( 0, N );
60+
// returns <Float64Array>[ ~0.98, ~0.92, ~0.83, ~0.7, ~0.56, ~0.38, ~0.2, ~0.0 ]
61+
62+
var twiddleFactors = workspace.slice( 2*N, 3*N );
63+
// returns <Float64Array>[ 0, ~0.707, ~0.707, 0, 0, 0, 0, 0 ]
64+
65+
var factors = workspace.slice( 3*N, ( 3*N ) + 4 );
66+
// returns <Float64Array>[ 8, 2, 2, 4 ]
67+
```
68+
69+
The function accepts the following arguments:
70+
71+
- **N**: length of the sequence to transform.
72+
- **workspace**: workspace array.
73+
- **strideW**: stride length for `workspace`.
74+
- **offsetW**: starting index for `workspace`.
75+
76+
</section>
77+
78+
<!-- /.usage -->
79+
80+
<!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
81+
82+
<section class="notes">
83+
84+
## Notes
85+
86+
- The workspace array is divided into four sections:
87+
88+
```text
89+
size = N N N 2+ceil(log2(N)/2)
90+
↓ ↓ ↓ ↓
91+
| cosine table | scratch / workspace | twiddle factors | radix factor table |
92+
↑ ↑ ↑ ↑
93+
i = 0 ... N ... 2N ... 3N ...
94+
```
95+
96+
- **cosine table**: a table of precomputed cosine coefficients used by quarter-wave cosine transforms.
97+
- **scratch/workspace**: used as a scratch space when performing transforms. This section is not updated during initialization.
98+
- **twiddle factors**: a table of reusable complex-exponential constants stored as cosine/sine pairs.
99+
- **radix factor table**: a table containing the sequence length `N`, the number of factors into which `N` was decomposed, and the individual integer radix factors.
100+
101+
- In general, a workspace array should have `3N + 34` indexed elements (as `log2(N)/2 ≤ 32` for all `2^64`). During initialization, only the sections for storing the cosine coefficients, twiddle factors, and the factorization of `N` are updated.
102+
103+
- The radix factor table is comprised as follows:
104+
105+
```text
106+
| sequence_length | number_of_factors | integer_factors |
107+
```
108+
109+
</section>
110+
111+
<!-- /.notes -->
112+
113+
<section class="examples">
114+
115+
## Examples
116+
117+
<!-- eslint no-undef: "error" -->
118+
119+
```javascript
120+
var Float64Array = require( '@stdlib/array/float64' );
121+
var zeroTo = require( '@stdlib/array/zero-to' );
122+
var logEach = require( '@stdlib/console/log-each' );
123+
var cosqi = require( '@stdlib/fft/base/fftpack/cosqi' );
124+
125+
var N = 8;
126+
var workspace = new Float64Array( ( 3*N ) + 34 );
127+
128+
cosqi( N, workspace, 1, 0 );
129+
console.log( 'Sequence length: %d', N );
130+
131+
console.log( 'Cosine table:' );
132+
var idx = zeroTo( N, 'generic' );
133+
logEach( ' workspace[ %d ] = %0.4f', idx, workspace.slice( 0, N ) );
134+
135+
console.log( 'Twiddle factors:' );
136+
idx = zeroTo( N, 'generic' );
137+
logEach( ' workspace[ %d ] = %0.4f', idx, workspace.slice( 2*N, 3*N ) );
138+
139+
console.log( 'Factorization:' );
140+
var nf = workspace[ (3*N)+1 ];
141+
142+
console.log( ' number of factors: %d', nf );
143+
idx = zeroTo( nf, 'generic' );
144+
logEach( ' factor[ %d ]: %d', idx, workspace.slice( (3*N)+2, (3*N)+2+nf ) );
145+
```
146+
147+
</section>
148+
149+
<!-- /.examples -->
150+
151+
<!-- Section to include cited references. If references are included, add a horizontal rule *before* the section. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
152+
153+
<section class="references">
154+
155+
</section>
156+
157+
<!-- /.references -->
158+
159+
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
160+
161+
<section class="related">
162+
163+
</section>
164+
165+
<!-- /.related -->
166+
167+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
168+
169+
<section class="links">
170+
171+
</section>
172+
173+
<!-- /.links -->
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2026 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var bench = require( '@stdlib/bench' );
24+
var format = require( '@stdlib/string/format' );
25+
var isnan = require( '@stdlib/math/base/assert/is-nan' );
26+
var Float64Array = require( '@stdlib/array/float64' );
27+
var pkg = require( './../package.json' ).name;
28+
var cosqi = require( './../lib' );
29+
30+
31+
// FUNCTIONS //
32+
33+
/**
34+
* Creates a benchmark function.
35+
*
36+
* @private
37+
* @param {PositiveInteger} N - sequence length
38+
* @returns {Function} benchmark function
39+
*/
40+
function createBenchmark( N ) {
41+
var workspace = new Float64Array( ( 3*N ) + 34 );
42+
return benchmark;
43+
44+
/**
45+
* Benchmark function.
46+
*
47+
* @private
48+
* @param {Benchmark} b - benchmark instance
49+
*/
50+
function benchmark( b ) {
51+
var i;
52+
53+
b.tic();
54+
for ( i = 0; i < b.iterations; i++ ) {
55+
cosqi( N, workspace, 1, 0 );
56+
if ( isnan( workspace[ ( 2*N ) + 1 ] ) ) {
57+
b.fail( 'should not return NaN' );
58+
}
59+
}
60+
b.toc();
61+
if ( isnan( workspace[ ( 2*N ) + 1 ] ) ) {
62+
b.fail( 'should not return NaN' );
63+
}
64+
b.pass( 'benchmark finished' );
65+
b.end();
66+
}
67+
}
68+
69+
70+
// MAIN //
71+
72+
/**
73+
* Main execution sequence.
74+
*
75+
* @private
76+
*/
77+
function main() {
78+
var lengths;
79+
var N;
80+
var f;
81+
var i;
82+
83+
lengths = [
84+
8,
85+
16,
86+
32,
87+
64,
88+
128,
89+
256,
90+
512,
91+
1024
92+
];
93+
94+
for ( i = 0; i < lengths.length; i++ ) {
95+
N = lengths[ i ];
96+
f = createBenchmark( N );
97+
bench( format( '%s:N=%d', pkg, N ), f );
98+
}
99+
}
100+
101+
main();
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
2+
{{alias}}( N, workspace, strideW, offsetW )
3+
Initializes a workspace array for performing a quarter-wave cosine
4+
transform.
5+
6+
The workspace array is divided into four sections:
7+
8+
1. cosine table: the section ranges from indices 0 to N-1 and is used to
9+
store a table of precomputed cosine coefficients used by quarter-wave
10+
cosine transforms.
11+
12+
2. scratch/workspace: the section ranges from indices N to 2N-1 and is used
13+
while performing transforms. This section is not updated during
14+
initialization.
15+
16+
3. twiddle factors: the section ranges from indices 2N to 3N-1 and stores a
17+
table of reusable complex exponential constants as cosine/sine pairs.
18+
19+
4. radix factor table: the section starts at index 3N and stores the
20+
sequence length N, the number of factors into which N was decomposed, and
21+
the individual integer radix factors.
22+
23+
Any remaining array space remains as unused storage.
24+
25+
Parameters
26+
----------
27+
N: integer
28+
Length of the sequence.
29+
30+
workspace: ArrayLikeObject<number>
31+
Workspace array.
32+
33+
strideW: integer
34+
Stride length for `workspace`.
35+
36+
offsetW: integer
37+
Starting index for `workspace`.
38+
39+
Returns
40+
-------
41+
out: ArrayLikeObject<number>
42+
Workspace array.
43+
44+
Examples
45+
--------
46+
> var N = 8;
47+
> var workspace = new {{alias:@stdlib/array/float64}}( ( 3*N ) + 34 );
48+
> var out = {{alias}}( N, workspace, 1, 0 )
49+
<Float64Array>
50+
> var bool = ( out === workspace )
51+
true
52+
> var cosineTable = workspace.slice( 0, N )
53+
<Float64Array>[ ~0.98, ~0.92, ~0.83, ~0.7, ~0.56, ~0.38, ~0.2, ~0.0 ]
54+
> var twiddleFactors = workspace.slice( 2*N, 3*N )
55+
<Float64Array>[ 0, ~0.707, ~0.707, 0, 0, 0, 0, 0 ]
56+
> var factors = workspace.slice( 3*N, ( 3*N ) + 4 )
57+
<Float64Array>[ 8, 2, 2, 4 ]
58+
59+
See Also
60+
--------
61+

0 commit comments

Comments
 (0)