Skip to content

Commit 5318182

Browse files
steff456kgryte
andauthored
feat!: refactor API and add C API to math/base/special/cexp
BREAKING CHANGE: remove support for `out` argument To migrate, users should provide a `Complex128` object, rather than an output array and real and imaginary components. PR-URL: #972 Co-authored-by: Athan Reines <kgryte@gmail.com> Reviewed-by: Athan Reines <kgryte@gmail.com> Private-ref: stdlib-js/todo#1454
1 parent d22c7ad commit 5318182

File tree

25 files changed

+1812
-381
lines changed

25 files changed

+1812
-381
lines changed

lib/node_modules/@stdlib/math/base/special/cexp/README.md

+137-31
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ limitations under the License.
2020

2121
# exp
2222

23-
> Compute the [exponential][exponential-function] function of a complex number.
23+
> Evaluate the [exponential][exponential-function] function for a double-precision complex floating-point number.
2424
25-
<section class="intro">
25+
<section class="intro">
2626

2727
The [exponential][exponential-function] function of a complex number is defined as
2828

@@ -51,30 +51,32 @@ The [exponential][exponential-function] function of a complex number is defined
5151
var cexp = require( '@stdlib/math/base/special/cexp' );
5252
```
5353

54-
#### cexp( \[out,] re, im )
54+
#### cexp( z )
5555

56-
Evaluates the [exponential][exponential-function] function with a `complex` argument comprised of a **real** component `re` and an **imaginary** component `im`.
56+
Evaluates the [exponential][exponential-function] function for a double-precision complex floating-point number.
5757

5858
```javascript
59-
var v = cexp( 0.0, 0.0 );
60-
// returns [ 1.0, 0.0 ]
59+
var Complex128 = require( '@stdlib/complex/float64' );
60+
var real = require( '@stdlib/complex/real' );
61+
var imag = require( '@stdlib/complex/imag' );
6162

62-
v = cexp( 0.0, 1.0 );
63-
// returns [ ~0.540, ~0.841 ]
64-
```
63+
var v = cexp( new Complex128( 0.0, 0.0 ) );
64+
// returns <Complex128>
6565

66-
By default, the function returns real and imaginary components as a two-element `array`. To avoid unnecessary memory allocation, the function supports providing an output (destination) object.
66+
var re = real( v );
67+
// returns 1.0
6768

68-
```javascript
69-
var Float64Array = require( '@stdlib/array/float64' );
69+
var im = imag( v );
70+
// returns 0.0
7071

71-
var out = new Float64Array( 2 );
72+
v = cexp( new Complex128( 0.0, 1.0 ) );
73+
// returns <Complex128>
7274

73-
var v = cexp( out, 0.0, 1.0 );
74-
// returns <Float64Array>[ ~0.540, ~0.841 ]
75+
re = real( v );
76+
// returns ~0.540
7577

76-
var bool = ( v === out );
77-
// returns true
78+
im = imag( v );
79+
// returns ~0.841
7880
```
7981

8082
</section>
@@ -89,35 +91,139 @@ var bool = ( v === out );
8991

9092
```javascript
9193
var Complex128 = require( '@stdlib/complex/float64' );
92-
var randu = require( '@stdlib/random/base/randu' );
93-
var round = require( '@stdlib/math/base/special/round' );
94-
var real = require( '@stdlib/complex/real' );
95-
var imag = require( '@stdlib/complex/imag' );
94+
var discreteUniform = require( '@stdlib/random/base/discrete-uniform' );
9695
var cexp = require( '@stdlib/math/base/special/cexp' );
9796

98-
var re;
99-
var im;
97+
function randomComplex() {
98+
var re = discreteUniform( -50, 50 );
99+
var im = discreteUniform( -50, 50 );
100+
return new Complex128( re, im );
101+
}
102+
100103
var z1;
101104
var z2;
102-
var o;
103105
var i;
104-
105106
for ( i = 0; i < 100; i++ ) {
106-
re = round( randu()*100.0 ) - 50.0;
107-
im = round( randu()*100.0 ) - 50.0;
108-
z1 = new Complex128( re, im );
107+
z1 = randomComplex();
108+
z2 = cexp( z1 );
109+
console.log( 'cexp(%s) = %s', z1.toString(), z2.toString() );
110+
}
111+
```
109112

110-
o = cexp( real(z1), imag(z1) );
111-
z2 = new Complex128( o[ 0 ], o[ 1 ] );
113+
</section>
112114

113-
console.log( 'cexp(%s) = %s', z1.toString(), z2.toString() );
115+
<!-- /.examples -->
116+
117+
<!-- C interface documentation. -->
118+
119+
* * *
120+
121+
<section class="c">
122+
123+
## C APIs
124+
125+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
126+
127+
<section class="intro">
128+
129+
</section>
130+
131+
<!-- /.intro -->
132+
133+
<!-- C usage documentation. -->
134+
135+
<section class="usage">
136+
137+
### Usage
138+
139+
```c
140+
#include "stdlib/math/base/special/cexp.h"
141+
```
142+
143+
#### stdlib_base_cexp( z )
144+
145+
Evaluates the [exponential][exponential-function] function for a double-precision complex floating-point number.
146+
147+
```c
148+
#include "stdlib/complex/float64.h"
149+
#include "stdlib/complex/real.h"
150+
#include "stdlib/complex/imag.h"
151+
152+
stdlib_complex128_t z = stdlib_complex128( 0.0, 0.0 );
153+
stdlib_complex128_t out = stdlib_base_cexp( z );
154+
155+
double re = stdlib_real( out );
156+
// returns 1.0
157+
158+
double im = stdlib_imag( out );
159+
// returns 0.0
160+
```
161+
162+
The function accepts the following arguments:
163+
164+
- **z**: `[in] stdlib_complex128_t` input value.
165+
166+
```c
167+
stdlib_complex128_t stdlib_base_cexp( const stdlib_complex128_t z );
168+
```
169+
170+
</section>
171+
172+
<!-- /.usage -->
173+
174+
<!-- C API usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
175+
176+
<section class="notes">
177+
178+
</section>
179+
180+
<!-- /.notes -->
181+
182+
<!-- C API usage examples. -->
183+
184+
<section class="examples">
185+
186+
### Examples
187+
188+
```c
189+
#include "stdlib/math/base/special/cexp.h"
190+
#include "stdlib/complex/float64.h"
191+
#include "stdlib/complex/reim.h"
192+
#include <stdio.h>
193+
194+
int main() {
195+
const stdlib_complex128_t x[] = {
196+
stdlib_complex128( 3.14, 1.5 ),
197+
stdlib_complex128( -3.14, -1.5 ),
198+
stdlib_complex128( 0.0, 0.0 ),
199+
stdlib_complex128( 0.0/0.0, 0.0/0.0 )
200+
};
201+
202+
stdlib_complex128_t v;
203+
stdlib_complex128_t y;
204+
double re1;
205+
double im1;
206+
double re2;
207+
double im2;
208+
int i;
209+
for ( i = 0; i < 4; i++ ) {
210+
v = x[ i ];
211+
y = stdlib_base_cexp( v );
212+
stdlib_reim( v, &re1, &im1 );
213+
stdlib_reim( y, &re2, &im2 );
214+
printf( "cexp(%lf + %lfi) = %lf + %lfi\n", re1, im1, re2, im2 );
215+
}
114216
}
115217
```
116218

117219
</section>
118220

119221
<!-- /.examples -->
120222

223+
</section>
224+
225+
<!-- /.c -->
226+
121227
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
122228

123229
<section class="related">

lib/node_modules/@stdlib/math/base/special/cexp/benchmark/benchmark.js

+15-36
Original file line numberDiff line numberDiff line change
@@ -21,58 +21,37 @@
2121
// MODULES //
2222

2323
var bench = require( '@stdlib/bench' );
24-
var randu = require( '@stdlib/random/base/randu' );
25-
var isArray = require( '@stdlib/assert/is-array' );
24+
var uniform = require( '@stdlib/random/base/uniform' );
25+
var isnan = require( '@stdlib/math/base/assert/is-nan' );
26+
var Complex128 = require( '@stdlib/complex/float64' );
27+
var real = require( '@stdlib/complex/real' );
28+
var imag = require( '@stdlib/complex/imag' );
2629
var pkg = require( './../package.json' ).name;
2730
var cexp = require( './../lib' );
2831

2932

3033
// MAIN //
3134

3235
bench( pkg, function benchmark( b ) {
33-
var re;
34-
var im;
36+
var values;
3537
var y;
3638
var i;
3739

38-
b.tic();
39-
for ( i = 0; i < b.iterations; i++ ) {
40-
re = ( randu()*100.0 ) - 50.0;
41-
im = ( randu()*100.0 ) - 50.0;
42-
y = cexp( re, im );
43-
if ( y.length === 0 ) {
44-
b.fail( 'should not be empty' );
45-
}
46-
}
47-
b.toc();
48-
if ( !isArray( y ) ) {
49-
b.fail( 'should return an array' );
50-
}
51-
b.pass( 'benchmark finished' );
52-
b.end();
53-
});
54-
55-
bench( pkg+'::memory_reuse', function benchmark( b ) {
56-
var out;
57-
var re;
58-
var im;
59-
var y;
60-
var i;
61-
62-
out = new Array( 2 );
40+
values = [
41+
new Complex128( uniform( -50.0, 50.0 ), uniform( -50.0, 50.0 ) ),
42+
new Complex128( uniform( -50.0, 50.0 ), uniform( -50.0, 50.0 ) )
43+
];
6344

6445
b.tic();
6546
for ( i = 0; i < b.iterations; i++ ) {
66-
re = ( randu()*100.0 ) - 50.0;
67-
im = ( randu()*100.0 ) - 50.0;
68-
y = cexp( out, re, im );
69-
if ( y.length === 0 ) {
70-
b.fail( 'should not be empty' );
47+
y = cexp( values[ i%values.length ] );
48+
if ( typeof y !== 'object' ) {
49+
b.fail( 'should return a complex number' );
7150
}
7251
}
7352
b.toc();
74-
if ( !isArray( y ) ) {
75-
b.fail( 'should return an array' );
53+
if ( isnan( real( y ) ) || isnan( imag( y ) ) ) {
54+
b.fail( 'should not return NaN' );
7655
}
7756
b.pass( 'benchmark finished' );
7857
b.end();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2023 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 resolve = require( 'path' ).resolve;
24+
var bench = require( '@stdlib/bench' );
25+
var uniform = require( '@stdlib/random/base/uniform' );
26+
var isnan = require( '@stdlib/math/base/assert/is-nan' );
27+
var Complex128 = require( '@stdlib/complex/float64' );
28+
var real = require( '@stdlib/complex/real' );
29+
var imag = require( '@stdlib/complex/imag' );
30+
var tryRequire = require( '@stdlib/utils/try-require' );
31+
var pkg = require( './../package.json' ).name;
32+
33+
34+
// VARIABLES //
35+
36+
var cexp = tryRequire( resolve( __dirname, './../lib/native.js' ) );
37+
var opts = {
38+
'skip': ( cexp instanceof Error )
39+
};
40+
41+
42+
// MAIN //
43+
44+
bench( pkg+'::native', opts, function benchmark( b ) {
45+
var values;
46+
var y;
47+
var i;
48+
49+
values = [
50+
new Complex128( uniform( -500.0, 500.0 ), uniform( -500.0, 500.0 ) ),
51+
new Complex128( uniform( -500.0, 500.0 ), uniform( -500.0, 500.0 ) )
52+
];
53+
54+
b.tic();
55+
for ( i = 0; i < b.iterations; i++ ) {
56+
y = cexp( values[ i%values.length ] );
57+
if ( typeof y !== 'object' ) {
58+
b.fail( 'should return a complex number' );
59+
}
60+
}
61+
b.toc();
62+
if ( isnan( real( y ) ) || isnan( imag( y ) ) ) {
63+
b.fail( 'should not return NaN' );
64+
}
65+
b.pass( 'benchmark finished' );
66+
b.end();
67+
});

0 commit comments

Comments
 (0)