From 01c52aba821909c8373f9f753ee155582ba07257 Mon Sep 17 00:00:00 2001 From: Stephannie Jimenez Date: Tue, 14 Mar 2023 16:15:18 -0500 Subject: [PATCH 1/4] remove: remove out keyword and add support for Complex128 data type in cexp BREAKING CHANGE: out keyword no longer supported, now downstream libraries need to create a complex dtype to use this API --- .../@stdlib/math/base/special/cexp/README.md | 40 ++-- .../base/special/cexp/benchmark/benchmark.js | 45 ++--- .../math/base/special/cexp/docs/repl.txt | 42 ++--- .../base/special/cexp/docs/types/index.d.ts | 52 +++--- .../math/base/special/cexp/docs/types/test.ts | 48 ++--- .../math/base/special/cexp/examples/index.js | 6 +- .../math/base/special/cexp/lib/cexp.js | 87 --------- .../math/base/special/cexp/lib/index.js | 22 +-- .../math/base/special/cexp/lib/main.js | 87 +++++++-- .../math/base/special/cexp/package.json | 2 +- .../math/base/special/cexp/test/test.js | 175 ++++++++++-------- 11 files changed, 265 insertions(+), 341 deletions(-) delete mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/lib/cexp.js diff --git a/lib/node_modules/@stdlib/math/base/special/cexp/README.md b/lib/node_modules/@stdlib/math/base/special/cexp/README.md index da53b36fccd9..127fa0b27d6e 100644 --- a/lib/node_modules/@stdlib/math/base/special/cexp/README.md +++ b/lib/node_modules/@stdlib/math/base/special/cexp/README.md @@ -20,9 +20,9 @@ limitations under the License. # exp -> Compute the [exponential][exponential-function] function of a complex number. +> Compute the [exponential][exponential-function] function of double-precision complex floating-point number. -
+
The [exponential][exponential-function] function of a complex number is defined as @@ -51,30 +51,32 @@ The [exponential][exponential-function] function of a complex number is defined var cexp = require( '@stdlib/math/base/special/cexp' ); ``` -#### cexp( \[out,] re, im ) +#### cexp( z ) -Evaluates the [exponential][exponential-function] function with a `complex` argument comprised of a **real** component `re` and an **imaginary** component `im`. +Evaluates the [exponential][exponential-function] function with a double-precision complex floating-point number. ```javascript -var v = cexp( 0.0, 0.0 ); -// returns [ 1.0, 0.0 ] +var Complex128 = require( '@stdlib/complex/float64' ); +var real = require( '@stdlib/complex/real' ); +var imag = require( '@stdlib/complex/imag' ); -v = cexp( 0.0, 1.0 ); -// returns [ ~0.540, ~0.841 ] -``` +var v = cexp( new Complex128( 0.0, 0.0 ) ); +// returns -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. +var re = real( v ); +// returns 1.0 -```javascript -var Float64Array = require( '@stdlib/array/float64' ); +var im = imag( v ); +// returns 0.0 -var out = new Float64Array( 2 ); +v = cexp( new Complex128( 0.0, 1.0 ) ); +// returns -var v = cexp( out, 0.0, 1.0 ); -// returns [ ~0.540, ~0.841 ] +re = real( v ); +// returns ~0.540 -var bool = ( v === out ); -// returns true +im = imag( v ); +// returns ~0.841 ```
@@ -99,7 +101,6 @@ var re; var im; var z1; var z2; -var o; var i; for ( i = 0; i < 100; i++ ) { @@ -107,8 +108,7 @@ for ( i = 0; i < 100; i++ ) { im = round( randu()*100.0 ) - 50.0; z1 = new Complex128( re, im ); - o = cexp( real(z1), imag(z1) ); - z2 = new Complex128( o[ 0 ], o[ 1 ] ); + z2 = cexp( z1 ); console.log( 'cexp(%s) = %s', z1.toString(), z2.toString() ); } diff --git a/lib/node_modules/@stdlib/math/base/special/cexp/benchmark/benchmark.js b/lib/node_modules/@stdlib/math/base/special/cexp/benchmark/benchmark.js index 0f1d94f6de1c..0130f19e4c59 100644 --- a/lib/node_modules/@stdlib/math/base/special/cexp/benchmark/benchmark.js +++ b/lib/node_modules/@stdlib/math/base/special/cexp/benchmark/benchmark.js @@ -21,8 +21,9 @@ // MODULES // var bench = require( '@stdlib/bench' ); -var randu = require( '@stdlib/random/base/randu' ); -var isArray = require( '@stdlib/assert/is-array' ); +var uniform = require( '@stdlib/random/base/uniform' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var Complex128 = require( '@stdlib/complex/float64' ); var pkg = require( './../package.json' ).name; var cexp = require( './../lib' ); @@ -30,48 +31,24 @@ var cexp = require( './../lib' ); // MAIN // bench( pkg, function benchmark( b ) { - var re; - var im; + var values; var y; var i; - b.tic(); - for ( i = 0; i < b.iterations; i++ ) { - re = ( randu()*100.0 ) - 50.0; - im = ( randu()*100.0 ) - 50.0; - y = cexp( re, im ); - if ( y.length === 0 ) { - b.fail( 'should not be empty' ); - } - } - b.toc(); - if ( !isArray( y ) ) { - b.fail( 'should return an array' ); - } - b.pass( 'benchmark finished' ); - b.end(); -}); - -bench( pkg+'::memory_reuse', function benchmark( b ) { - var out; - var re; - var im; - var y; - var i; - - out = new Array( 2 ); + values = [ + new Complex128( uniform( -50.0, 50.0 ), uniform( -50.0, 50.0 ) ), + new Complex128( uniform( -50.0, 50.0 ), uniform( -50.0, 50.0 ) ) + ]; b.tic(); for ( i = 0; i < b.iterations; i++ ) { - re = ( randu()*100.0 ) - 50.0; - im = ( randu()*100.0 ) - 50.0; - y = cexp( out, re, im ); - if ( y.length === 0 ) { + y = cexp( values[ i%values.length ] ); + if ( isnan( y ) ) { b.fail( 'should not be empty' ); } } b.toc(); - if ( !isArray( y ) ) { + if ( isnan( y ) ) { b.fail( 'should return an array' ); } b.pass( 'benchmark finished' ); diff --git a/lib/node_modules/@stdlib/math/base/special/cexp/docs/repl.txt b/lib/node_modules/@stdlib/math/base/special/cexp/docs/repl.txt index a922294f6ba5..cf205d280cdb 100644 --- a/lib/node_modules/@stdlib/math/base/special/cexp/docs/repl.txt +++ b/lib/node_modules/@stdlib/math/base/special/cexp/docs/repl.txt @@ -1,36 +1,32 @@ -{{alias}}( [out,] re, im ) - Computes the exponential function of a complex number. +{{alias}}( z ) + Computes the exponential function of a double-precision complex + floating-point number. Parameters ---------- - out: Array|TypedArray|Object (optional) - Output array. - - re: number - Real component. - - im: number - Imaginary component. + z: Complex128 + Complex number. Returns ------- - out: Array|TypedArray|Object - Real and imaginary components. + out: Complex128 + Complex number. Examples -------- - > var y = {{alias}}( 0.0, 0.0 ) - [ 1.0, 0.0 ] - - > y = {{alias}}( 0.0, 1.0 ) - [ ~0.540, ~0.841 ] - - > var out = new {{alias:@stdlib/array/float64}}( 2 ); - > var v = {{alias}}( out, 0.0, 1.0 ) - [ ~0.540, ~0.841 ] - > var bool = ( v === out ) - true + > var y = {{alias}}( new {{alias:@stdlib/complex/float64}}( 0.0, 0.0 ) ) + + > var re = {{alias:@stdlib/complex/real}}( y ) + 1.0 + > var im = {{alias:@stdlib/complex/imag}}( y ) + 0.0 + > y = {{alias}}( new {{alias:@stdlib/complex/float64}}( 0.0, 1.0 ) ) + + > var re = {{alias:@stdlib/complex/real}}( y ) + ~0.540 + > var im = {{alias:@stdlib/complex/imag}}( y ) + ~0.841 See Also -------- diff --git a/lib/node_modules/@stdlib/math/base/special/cexp/docs/types/index.d.ts b/lib/node_modules/@stdlib/math/base/special/cexp/docs/types/index.d.ts index 636085591b39..b297f48e58ad 100644 --- a/lib/node_modules/@stdlib/math/base/special/cexp/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/math/base/special/cexp/docs/types/index.d.ts @@ -20,45 +20,43 @@ /// -import { ArrayLike } from '@stdlib/types/array'; +import { Complex128 } from '@stdlib/types/object'; /** -* Computes the exponential function of a complex number. +* Computes the exponential function of a double-precision complex floating-point number. * -* @param out - output array -* @param re - real component -* @param im - imaginary component -* @returns real and imaginary components +* @param z - complex number +* @returns result * * @example -* var Float32Array = require( `@stdlib/array/float32` ); +* var Complex128 = require( `@stdlib/complex/float64` ); +* var real = require( `@stdlib/complex/real` ); +* var imag = require( `@stdlib/complex/imag` ); * -* var out = new Float32Array( 2 ); +* var v = cexp( new Complex128( 0.0, 0.0 ) ); +* // returns * -* var v = cexp( out, 0.0, 1.0 ); -* // returns [ ~0.540, ~0.841 ] +* var re = real( v ); +* // returns 1.0 * -* var bool = ( v === out ); -* // returns true -*/ -declare function cexp( out: ArrayLike, re: number, im: number ): ArrayLike; // tslint-disable-line max-line-length - -/** -* Computes the exponential function of a complex number. -* -* @param re - real component -* @param im - imaginary component -* @returns real and imaginary components +* var im = imag( v ); +* // returns 0.0 * * @example -* var v = cexp( 0.0, 0.0 ); -* // returns [ 1.0, 0.0 ] +* var Complex128 = require( `@stdlib/complex/float64` ); +* var real = require( `@stdlib/complex/real` ); +* var imag = require( `@stdlib/complex/imag` ); * -* @example -* var v = cexp( 1.0, 0.0 ); -* // returns [ ~2.718, 0.0 ] +* var v = cexp( new Complex128( 1.0, 0.0 ) ); +* // returns +* +* var re = real( v ); +* // returns ~2.718 +* +* var im = imag( v ); +* // returns 0.0 */ -declare function cexp( re: number, im: number ): ArrayLike; +declare function cexp( z: Complex128 ): Complex128; // EXPORTS // diff --git a/lib/node_modules/@stdlib/math/base/special/cexp/docs/types/test.ts b/lib/node_modules/@stdlib/math/base/special/cexp/docs/types/test.ts index fdf1ce056d3f..46820cc42abf 100644 --- a/lib/node_modules/@stdlib/math/base/special/cexp/docs/types/test.ts +++ b/lib/node_modules/@stdlib/math/base/special/cexp/docs/types/test.ts @@ -16,53 +16,31 @@ * limitations under the License. */ +import Complex128 = require( '@stdlib/complex/float64' ); import cexp = require( './index' ); // TESTS // -// The function returns an array of numbers... +// The function returns a complex number... { - cexp( 5, 3 ); // $ExpectType ArrayLike - cexp( [], 5, 3 ); // $ExpectType ArrayLike + cexp( new Complex128( 1.0, 2.0 ) ); // $ExpectType Complex128 } -// The compiler throws an error if the function is provided a real component which is not a number... +// The compiler throws an error if the function is provided a value other than a complex number... { - cexp( true, 3 ); // $ExpectError - cexp( false, 3 ); // $ExpectError - cexp( null, 3 ); // $ExpectError - cexp( undefined, 3 ); // $ExpectError - cexp( '5', 3 ); // $ExpectError - cexp( [], 3 ); // $ExpectError - cexp( {}, 3 ); // $ExpectError - cexp( ( x: number ): number => x, 3 ); // $ExpectError -} - -// The compiler throws an error if the function is provided an imaginary component which is not a number... -{ - cexp( 5, true ); // $ExpectError - cexp( 5, false ); // $ExpectError - cexp( 5, null ); // $ExpectError - cexp( 5, undefined ); // $ExpectError - cexp( 5, '5' ); // $ExpectError - cexp( 5, [] ); // $ExpectError - cexp( 5, {} ); // $ExpectError - cexp( 5, ( x: number ): number => x ); // $ExpectError -} - -// The compiler throws an error if the function is provided an output array which is not array-like... -{ - cexp( true, 5, 3 ); // $ExpectError - cexp( false, 5, 3 ); // $ExpectError - cexp( 'abc', 5, 3 ); // $ExpectError - cexp( {}, 5, 3 ); // $ExpectError - cexp( ( x: number ): number => x, 5, 3 ); // $ExpectError - cexp( 123, 5, 3 ); // $ExpectError + cexp( 2 ); // $ExpectError + cexp( true ); // $ExpectError + cexp( false ); // $ExpectError + cexp( null ); // $ExpectError + cexp( undefined ); // $ExpectError + cexp( '5' ); // $ExpectError + cexp( [] ); // $ExpectError + cexp( {} ); // $ExpectError + cexp( ( x: number ): number => x ); // $ExpectError } // The compiler throws an error if the function is provided insufficient arguments... { cexp(); // $ExpectError - cexp( 2 ); // $ExpectError } diff --git a/lib/node_modules/@stdlib/math/base/special/cexp/examples/index.js b/lib/node_modules/@stdlib/math/base/special/cexp/examples/index.js index 8d8403ab855b..c245c7be2a54 100644 --- a/lib/node_modules/@stdlib/math/base/special/cexp/examples/index.js +++ b/lib/node_modules/@stdlib/math/base/special/cexp/examples/index.js @@ -21,15 +21,12 @@ var Complex128 = require( '@stdlib/complex/float64' ); var randu = require( '@stdlib/random/base/randu' ); var round = require( '@stdlib/math/base/special/round' ); -var real = require( '@stdlib/complex/real' ); -var imag = require( '@stdlib/complex/imag' ); var cexp = require( './../lib' ); var re; var im; var z1; var z2; -var o; var i; for ( i = 0; i < 100; i++ ) { @@ -37,8 +34,7 @@ for ( i = 0; i < 100; i++ ) { im = round( randu()*100.0 ) - 50.0; z1 = new Complex128( re, im ); - o = cexp( real(z1), imag(z1) ); - z2 = new Complex128( o[ 0 ], o[ 1 ] ); + z2 = cexp( z1 ); console.log( 'cexp(%s) = %s', z1.toString(), z2.toString() ); } diff --git a/lib/node_modules/@stdlib/math/base/special/cexp/lib/cexp.js b/lib/node_modules/@stdlib/math/base/special/cexp/lib/cexp.js deleted file mode 100644 index a02b72f9ddaa..000000000000 --- a/lib/node_modules/@stdlib/math/base/special/cexp/lib/cexp.js +++ /dev/null @@ -1,87 +0,0 @@ -/** -* @license Apache-2.0 -* -* Copyright (c) 2018 The Stdlib Authors. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -'use strict'; - -// MODULES // - -var copysign = require( '@stdlib/math/base/special/copysign' ); -var sincos = require( '@stdlib/math/base/special/sincos' ).assign; -var isnan = require( '@stdlib/math/base/assert/is-nan' ); -var isInfinite = require( '@stdlib/math/base/assert/is-infinite' ); -var exp = require( '@stdlib/math/base/special/exp' ); -var PINF = require( '@stdlib/constants/float64/pinf' ); -var NINF = require( '@stdlib/constants/float64/ninf' ); - - -// MAIN // - -/** -* Computes the exponential function of a complex number. -* -* @private -* @param {(Array|TypedArray|Object)} out - output array -* @param {number} re - real component -* @param {number} im - imaginary component -* @returns {(Array|TypedArray|Object)} output array -* -* @example -* var out = [ 0.0, 0.0 ]; -* -* var v = cexp( out, 0.0, 1.0 ); -* // returns [ ~0.540, ~0.841 ] -* -* var bool = ( v === out ); -* // returns true -*/ -function cexp( out, re, im ) { - var tmp; - var e; - if ( isnan( re ) ) { - out[ 0 ] = NaN; - out[ 1 ] = ( im === 0.0 ) ? im : re; - } else if ( isInfinite( im ) ) { - if ( re === PINF ) { - out[ 0 ] = -re; - out[ 1 ] = NaN; - } else if ( re === NINF ) { - out[ 0 ] = -0.0; - out[ 1 ] = copysign( 0.0, im ); - } else { - out[ 0 ] = NaN; - out[ 1 ] = NaN; - } - } else { - e = exp( re ); - if ( im === 0.0 ) { - out[ 0 ] = e; - out[ 1 ] = im; - } else { - sincos( im, out, 1, 0 ); - tmp = out[ 0 ]; - out[ 0 ] = out[ 1 ] * e; - out[ 1 ] = tmp * e; - } - } - return out; -} - - -// EXPORTS // - -module.exports = cexp; diff --git a/lib/node_modules/@stdlib/math/base/special/cexp/lib/index.js b/lib/node_modules/@stdlib/math/base/special/cexp/lib/index.js index 044969f5e226..1506d7360f09 100644 --- a/lib/node_modules/@stdlib/math/base/special/cexp/lib/index.js +++ b/lib/node_modules/@stdlib/math/base/special/cexp/lib/index.js @@ -19,26 +19,24 @@ 'use strict'; /** -* Compute the exponential function of a complex number. +* Compute the exponential function of a double-precision floating-point complex number. * * @module @stdlib/math/base/special/cexp * * @example +* var Complex128 = require( '@stdlib/complex/float64' ); +* var real = require( '@stdlib/complex/real' ); +* var imag = require( '@stdlib/complex/imag' ); * var cexp = require( '@stdlib/math/base/special/cexp' ); * -* var v = cexp( 0.0, 0.0 ); -* // returns [ 1.0, 0.0 ] +* var v = cexp( new Complex128( 0.0, 0.0 ) ); +* // returns * -* @example -* var cexp = require( '@stdlib/math/base/special/cexp' ); -* -* var out = [ 0.0, 0.0 ]; -* -* var v = cexp( out, 0.0, 1.0 ); -* // returns [ ~0.540, ~0.841 ] +* var re = real( v ); +* // returns 1.0 * -* var bool = ( v === out ); -* // returns true +* var im = imag( v ); +* // returns 0.0 */ // MODULES // diff --git a/lib/node_modules/@stdlib/math/base/special/cexp/lib/main.js b/lib/node_modules/@stdlib/math/base/special/cexp/lib/main.js index 2b82b2c95c56..2a3bd427cc0c 100644 --- a/lib/node_modules/@stdlib/math/base/special/cexp/lib/main.js +++ b/lib/node_modules/@stdlib/math/base/special/cexp/lib/main.js @@ -20,7 +20,16 @@ // MODULES // -var computeExp = require( './cexp.js' ); +var Complex128 = require('@stdlib/complex/float64'); +var copysign = require( '@stdlib/math/base/special/copysign' ); +var sincos = require( '@stdlib/math/base/special/sincos' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var isInfinite = require( '@stdlib/math/base/assert/is-infinite' ); +var exp = require( '@stdlib/math/base/special/exp' ); +var PINF = require( '@stdlib/constants/float64/pinf' ); +var NINF = require( '@stdlib/constants/float64/ninf' ); +var real = require( '@stdlib/complex/real' ); +var imag = require( '@stdlib/complex/imag' ); // MAIN // @@ -28,33 +37,73 @@ var computeExp = require( './cexp.js' ); /** * Computes the exponential function of a complex number. * -* @param {(Array|TypedArray|Object)} [out] - output array -* @param {number} re - real component -* @param {number} im - imaginary component -* @returns {(Array|TypedArray|Object)} output array +* @param {Complex128} z - complex number +* @returns {Complex128} result * * @example -* var v = cexp( 0.0, 0.0 ); -* // returns [ 1.0, 0.0 ] +* var Complex128 = require( '@stdlib/complex/float64' ); +* var real = require( '@stdlib/complex/real' ); +* var imag = require( '@stdlib/complex/imag' ); +* var cexp = require( '@stdlib/math/base/special/cexp' ); * -* @example -* var v = cexp( 1.0, 0.0 ); -* // returns [ ~2.718, 0.0 ] +* var v = cexp( new Complex128( 0.0, 0.0 ) ); +* // returns +* +* var re = real( v ); +* // returns 1.0 +* +* var im = imag( v ); +* // returns 0.0 * * @example -* var out = [ 0.0, 0.0 ]; +* var Complex128 = require( '@stdlib/complex/float64' ); +* var real = require( '@stdlib/complex/real' ); +* var imag = require( '@stdlib/complex/imag' ); +* var cexp = require( '@stdlib/math/base/special/cexp' ); * -* var v = cexp( out, 1.0, 0.0 ); -* // returns [ ~2.718, 0.0 ] +* var v = cexp( new Complex128( 1.0, 0.0 ) ); +* // returns * -* var bool = ( v === out ); -* // returns true +* var re = real( v ); +* // returns ~2.718 +* +* var im = imag( v ); +* // returns 0.0 */ -function cexp( out, re, im ) { - if ( arguments.length === 2 ) { - return computeExp( [ 0.0, 0.0 ], out, re ); +function cexp( z ) { + var out; + var im; + var re; + var e; + + re = real( z ); + im = imag( z ); + + if ( isnan( re ) ) { + re = NaN; + im = ( im === 0.0 ) ? im : re; + } else if ( isInfinite( im ) ) { + if ( re === PINF ) { + re = -re; + im = NaN; + } else if ( re === NINF ) { + re = -0.0; + im = copysign( 0.0, im ); + } else { + re = NaN; + im = NaN; + } + } else { + e = exp( re ); + if ( im === 0.0 ) { + re = e; + } else { + out = sincos( im ); + re = out[ 1 ] * e; + im = out[ 0 ] * e; + } } - return computeExp( out, re, im ); + return new Complex128( re, im ); } diff --git a/lib/node_modules/@stdlib/math/base/special/cexp/package.json b/lib/node_modules/@stdlib/math/base/special/cexp/package.json index 8b848adea9fb..cf8cd514048a 100644 --- a/lib/node_modules/@stdlib/math/base/special/cexp/package.json +++ b/lib/node_modules/@stdlib/math/base/special/cexp/package.json @@ -1,7 +1,7 @@ { "name": "@stdlib/math/base/special/cexp", "version": "0.0.0", - "description": "Compute the exponential function of a complex number.", + "description": "Compute the exponential function of a double-precision complex floating-point number.", "license": "Apache-2.0", "author": { "name": "The Stdlib Authors", diff --git a/lib/node_modules/@stdlib/math/base/special/cexp/test/test.js b/lib/node_modules/@stdlib/math/base/special/cexp/test/test.js index 9171ef2a9610..f3a0336b7d5f 100644 --- a/lib/node_modules/@stdlib/math/base/special/cexp/test/test.js +++ b/lib/node_modules/@stdlib/math/base/special/cexp/test/test.js @@ -22,13 +22,15 @@ var tape = require( 'tape' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); -var isArray = require( '@stdlib/assert/is-array' ); var isPositiveZero = require( '@stdlib/math/base/assert/is-positive-zero' ); var isNegativeZero = require( '@stdlib/math/base/assert/is-negative-zero' ); var abs = require( '@stdlib/math/base/special/abs' ); var EPS = require( '@stdlib/constants/float64/eps' ); var PINF = require( '@stdlib/constants/float64/pinf' ); var NINF = require( '@stdlib/constants/float64/ninf' ); +var Complex128 = require( '@stdlib/complex/float64' ); +var real = require( '@stdlib/complex/real' ); +var imag = require( '@stdlib/complex/imag' ); var cexp = require( './../lib' ); @@ -47,20 +49,11 @@ tape( 'main export is a function', function test( t ) { }); tape( 'the function returns an output array', function test( t ) { - var result = cexp( 0.0, 0.0 ); - t.strictEqual( isArray( result ), true, 'returns expected value' ); - t.deepEqual( result, [ 1.0, 0.0 ], 'returns expected value' ); - t.end(); -}); - -tape( 'the function supports providing an optional output array', function test( t ) { - var result; - var out; + var v; - out = [ 0.0, 0.0 ]; - result = cexp( out, 0.0, 0.0 ); - t.deepEqual( out, [ 1.0, 0.0 ], 'returns expected value' ); - t.strictEqual( out, result, 'returns output array' ); + v = cexp( new Complex128( 0.0, 0.0 ) ); + t.strictEqual( real( v ), 1.0, 'returns expected value' ); + t.strictEqual( imag( v ), 0.0, 'returns expected value' ); t.end(); }); @@ -80,20 +73,20 @@ tape( 'the function computes exp(z) for pure imaginary z', function test( t ) { expim = pureImaginary.expim; for ( i = 0; i < re.length; i++ ) { - q = cexp( re[ i ], im[ i ] ); - if ( q[ 0 ] === expre[ i ] ) { - t.strictEqual( q[ 0 ], expre[ i ], 'returns expected real component' ); + q = cexp( new Complex128( re[ i ], im[ i ] ) ); + if ( real( q ) === expre[ i ] ) { + t.strictEqual( real( q ), expre[ i ], 'returns expected real component' ); } else { - delta = abs( q[ 0 ] - expre[ i ] ); + delta = abs( real( q ) - expre[ i ] ); tol = EPS * abs( expre[ i ] ); - t.ok( delta <= tol, 'within tolerance. z: '+re[i]+'+ '+im[i]+'i. real: '+q[0]+'. expected: '+expre[i]+'. delta: '+delta+'. tol: '+tol+'.' ); + t.ok( delta <= tol, 'within tolerance. z: '+re[i]+'+ '+im[i]+'i. real: '+real( q )+'. expected: '+expre[i]+'. delta: '+delta+'. tol: '+tol+'.' ); } - if ( q[ 1 ] === expim[ i ] ) { - t.strictEqual( q[ 1 ], expim[ i ], 'returns expected imaginary component' ); + if ( imag( q ) === expim[ i ] ) { + t.strictEqual( imag( q ), expim[ i ], 'returns expected imaginary component' ); } else { - delta = abs( q[ 1 ] - expim[ i ] ); + delta = abs( imag( q ) - expim[ i ] ); tol = EPS * abs( expim[ i ] ); - t.ok( delta <= tol, 'within tolerance. z: '+re[i]+'+ '+im[i]+'i. imag: '+q[1]+'. expected: '+expim[i]+'. delta: '+delta+'. tol: '+tol+'.' ); + t.ok( delta <= tol, 'within tolerance. z: '+re[i]+'+ '+im[i]+'i. imag: '+imag( q )+'. expected: '+expim[i]+'. delta: '+delta+'. tol: '+tol+'.' ); } } t.end(); @@ -115,128 +108,154 @@ tape( 'the function computes exp(z) for complex z', function test( t ) { expim = generalComplex.expim; for ( i = 0; i < re.length; i++ ) { - q = cexp( re[ i ], im[ i ] ); - if ( q[ 0 ] === expre[ i ] ) { - t.strictEqual( q[ 0 ], expre[ i ], 'returns expected real component' ); + q = cexp( new Complex128( re[ i ], im[ i ] ) ); + if ( real( q ) === expre[ i ] ) { + t.strictEqual( real( q ), expre[ i ], 'returns expected real component' ); } else { - delta = abs( q[ 0 ] - expre[ i ] ); + delta = abs( real( q ) - expre[ i ] ); tol = EPS * abs( expre[ i ] ); - t.ok( delta <= tol, 'within tolerance. z: '+re[i]+'+ '+im[i]+'i. real: '+q[0]+'. expected: '+expre[i]+'. delta: '+delta+'. tol: '+tol+'.' ); + t.ok( delta <= tol, 'within tolerance. z: '+re[i]+'+ '+im[i]+'i. real: '+real( q )+'. expected: '+expre[i]+'. delta: '+delta+'. tol: '+tol+'.' ); } - if ( q[ 1 ] === expim[ i ] ) { - t.strictEqual( q[ 1 ], expim[ i ], 'returns expected imaginary component' ); + if ( imag( q ) === expim[ i ] ) { + t.strictEqual( imag( q ), expim[ i ], 'returns expected imaginary component' ); } else { - delta = abs( q[ 1 ] - expim[ i ] ); + delta = abs( imag( q ) - expim[ i ] ); tol = EPS * abs( expim[ i ] ); - t.ok( delta <= tol, 'within tolerance. z: '+re[i]+'+ '+im[i]+'i. imag: '+q[1]+'. expected: '+expim[i]+'. delta: '+delta+'. tol: '+tol+'.' ); + t.ok( delta <= tol, 'within tolerance. z: '+re[i]+'+ '+im[i]+'i. imag: '+imag( q )+'. expected: '+expim[i]+'. delta: '+delta+'. tol: '+tol+'.' ); } } t.end(); }); tape( 'if imaginary component is `+Infinity`, the function returns `[NaN, NaN]`', function test( t ) { - var v = cexp( 0.0, PINF ); - t.strictEqual( isnan( v[ 0 ] ), true, 'returns NaN' ); - t.strictEqual( isnan( v[ 1 ] ), true, 'returns NaN' ); + var v; + + v = cexp( new Complex128( 0.0, PINF ) ); + t.strictEqual( isnan( real( v ) ), true, 'returns NaN' ); + t.strictEqual( isnan( imag( v ) ), true, 'returns NaN' ); t.end(); }); tape( 'if imaginary component is `-Infinity`, the function returns `[NaN, NaN]`', function test( t ) { - var v = cexp( 0.0, NINF ); - t.strictEqual( isnan( v[ 0 ] ), true, 'returns NaN' ); - t.strictEqual( isnan( v[ 1 ] ), true, 'returns NaN' ); + var v; + + v = cexp( new Complex128( 0.0, NINF ) ); + t.strictEqual( isnan( real( v ) ), true, 'returns NaN' ); + t.strictEqual( isnan( imag( v ) ), true, 'returns NaN' ); t.end(); }); tape( 'if real component is `-Infinity`, the function returns `[0.0, 0.0]`', function test( t ) { - var v = cexp( NINF, 1.0 ); - t.strictEqual( v[ 0 ], 0.0, 'returns 0.0' ); - t.strictEqual( v[ 1 ], 0.0, 'returns 0.0' ); + var v; + + v = cexp( new Complex128( NINF, 1.0 ) ); + t.strictEqual( real( v ), 0.0, 'returns 0.0' ); + t.strictEqual( imag( v ), 0.0, 'returns 0.0' ); t.end(); }); tape( 'if real component is `+Infinity` and imaginary component is `0.0`, the function returns `[+Infinity, 0.0]`', function test( t ) { - var v = cexp( PINF, 0.0 ); - t.strictEqual( v[ 0 ], PINF, 'returns +Infinity' ); - t.strictEqual( v[ 1 ], 0.0, 'returns 0.0' ); + var v; + + v = cexp( new Complex128( PINF, 0.0 ) ); + t.strictEqual( real( v ), PINF, 'returns +Infinity' ); + t.strictEqual( imag( v ), 0.0, 'returns 0.0' ); t.end(); }); tape( 'if real component is `NaN` and imaginary component is `0.0`, the function returns `[NaN, 0.0]`', function test( t ) { - var v = cexp( NaN, 0.0 ); - t.strictEqual( isnan( v[ 0 ] ), true, 'returns NaN' ); - t.strictEqual( v[ 1 ], 0.0, 'returns 0.0' ); + var v; + + v = cexp( new Complex128( NaN, 0.0 ) ); + t.strictEqual( isnan( real( v ) ), true, 'returns NaN' ); + t.strictEqual( imag( v ), 0.0, 'returns 0.0' ); t.end(); }); tape( 'if imaginary component is `NaN`, all components are `NaN`', function test( t ) { var v; - v = cexp( 5.0, NaN ); - t.strictEqual( isnan( v[ 0 ] ), true, 'returns NaN' ); - t.strictEqual( isnan( v[ 1 ] ), true, 'returns NaN' ); + v = cexp( new Complex128( 5.0, NaN ) ); + t.strictEqual( isnan( real( v ) ), true, 'returns NaN' ); + t.strictEqual( isnan( imag( v ) ), true, 'returns NaN' ); - v = cexp( 0.0, NaN ); - t.strictEqual( isnan( v[ 0 ] ), true, 'returns NaN' ); - t.strictEqual( isnan( v[ 1 ] ), true, 'returns NaN' ); + v = cexp( new Complex128( 0.0, NaN ) ); + t.strictEqual( isnan( real( v ) ), true, 'returns NaN' ); + t.strictEqual( isnan( imag( v ) ), true, 'returns NaN' ); - v = cexp( NaN, NaN ); - t.strictEqual( isnan( v[ 0 ] ), true, 'returns NaN' ); - t.strictEqual( isnan( v[ 1 ] ), true, 'returns NaN' ); + v = cexp( new Complex128( NaN, NaN ) ); + t.strictEqual( isnan( real( v ) ), true, 'returns NaN' ); + t.strictEqual( isnan( imag( v ) ), true, 'returns NaN' ); t.end(); }); tape( 'if imaginary component is `+0.0`, imaginary component of output is `+0.0`', function test( t ) { - var v = cexp( 3.0, 0.0 ); - t.strictEqual( isPositiveZero( v[ 1 ] ), true, 'returns +0.0' ); + var v; + + v = cexp( new Complex128( 3.0, 0.0 ) ); + t.strictEqual( isPositiveZero( imag( v ) ), true, 'returns +0.0' ); t.end(); }); tape( 'if imaginary component is `-0.0`, imaginary component of output is `-0.0`', function test( t ) { - var v = cexp( 3.0, -0.0 ); - t.strictEqual( isNegativeZero( v[ 1 ] ), true, 'returns -0.0' ); + var v; + + v = cexp( new Complex128( 3.0, -0.0 ) ); + t.strictEqual( isNegativeZero( imag( v ) ), true, 'returns -0.0' ); t.end(); }); tape( 'if real component is `NaN` and imaginary component is nonzero, all components are `NaN`', function test( t ) { - var v = cexp( NaN, 3.0 ); - t.strictEqual( isnan( v[ 0 ] ), true, 'returns NaN' ); - t.strictEqual( isnan( v[ 1 ] ), true, 'returns NaN' ); + var v; + + v = cexp( new Complex128( NaN, 3.0 ) ); + t.strictEqual( isnan( real( v ) ), true, 'returns NaN' ); + t.strictEqual( isnan( imag( v ) ), true, 'returns NaN' ); t.end(); }); tape( 'if real component is `NaN` and imaginary component is `+0.0`, imaginary component is `+0.0`', function test( t ) { - var v = cexp( NaN, 0.0 ); - t.strictEqual( isnan( v[ 0 ] ), true, 'returns NaN' ); - t.strictEqual( isPositiveZero( v[ 1 ] ), true, 'returns +0.0' ); + var v; + + v = cexp( new Complex128( NaN, 0.0 ) ); + t.strictEqual( isnan( real( v ) ), true, 'returns NaN' ); + t.strictEqual( isPositiveZero( imag( v ) ), true, 'returns +0.0' ); t.end(); }); tape( 'if real component is `NaN` and imaginary component is `-0.0`, imaginary component is `-0.0`', function test( t ) { - var v = cexp( NaN, -0.0 ); - t.strictEqual( isnan( v[ 0 ] ), true, 'returns NaN' ); - t.strictEqual( isNegativeZero( v[ 1 ] ), true, 'returns +0.0' ); + var v; + + v = cexp( new Complex128( NaN, -0.0 ) ); + t.strictEqual( isnan( real( v ) ), true, 'returns NaN' ); + t.strictEqual( isNegativeZero( imag( v ) ), true, 'returns +0.0' ); t.end(); }); tape( 'if real component is `+Infinity` and imaginary component is `+Infinity`, real part is `-Infinity` and imaginary part is `NaN`', function test( t ) { - var v = cexp( PINF, PINF ); - t.strictEqual( v[ 0 ], NINF, 'returns -Infinity' ); - t.strictEqual( isnan( v[ 1 ] ), true, 'returns NaN' ); + var v; + + v = cexp( new Complex128( PINF, PINF ) ); + t.strictEqual( real( v ), NINF, 'returns -Infinity' ); + t.strictEqual( isnan( imag( v ) ), true, 'returns NaN' ); t.end(); }); tape( 'if real component is `-Infinity` and imaginary component is `+Infinity`, real part is `-0.0` and imaginary part is `+0.0`', function test( t ) { - var v = cexp( NINF, PINF ); - t.strictEqual( isNegativeZero( v[ 0 ] ), true, 'returns -0.0' ); - t.strictEqual( isPositiveZero( v[ 1 ] ), true, 'returns +0.0' ); + var v; + + v = cexp( new Complex128( NINF, PINF ) ); + t.strictEqual( isNegativeZero( real( v ) ), true, 'returns -0.0' ); + t.strictEqual( isPositiveZero( imag( v ) ), true, 'returns +0.0' ); t.end(); }); tape( 'if real component is `-Infinity` and imaginary component is `-Infinity`, real part is `-0.0` and imaginary part is `-0.0`', function test( t ) { - var v = cexp( NINF, NINF ); - t.strictEqual( isNegativeZero( v[ 0 ] ), true, 'returns -0.0' ); - t.strictEqual( isNegativeZero( v[ 1 ] ), true, 'returns -0.0' ); + var v; + + v = cexp( new Complex128( NINF, NINF ) ); + t.strictEqual( isNegativeZero( real( v ) ), true, 'returns -0.0' ); + t.strictEqual( isNegativeZero( imag( v ) ), true, 'returns -0.0' ); t.end(); }); From 8661f9262564def9203ca8acc13b19f7c30a4531 Mon Sep 17 00:00:00 2001 From: Stephannie Jimenez Date: Tue, 14 Mar 2023 16:45:13 -0500 Subject: [PATCH 2/4] feat: add C implementation and native addon to cexp --- .../@stdlib/math/base/special/cexp/README.md | 111 +++++++ .../cexp/benchmark/benchmark.native.js | 66 +++++ .../special/cexp/benchmark/c/native/Makefile | 146 ++++++++++ .../cexp/benchmark/c/native/benchmark.c | 144 ++++++++++ .../math/base/special/cexp/binding.gyp | 170 +++++++++++ .../base/special/cexp/examples/c/Makefile | 146 ++++++++++ .../base/special/cexp/examples/c/example.c | 46 +++ .../math/base/special/cexp/include.gypi | 53 ++++ .../include/stdlib/math/base/special/cexp.h | 40 +++ .../math/base/special/cexp/lib/main.js | 2 +- .../math/base/special/cexp/lib/native.js | 73 +++++ .../math/base/special/cexp/manifest.json | 76 +++++ .../math/base/special/cexp/package.json | 1 + .../math/base/special/cexp/src/Makefile | 70 +++++ .../math/base/special/cexp/src/addon.c | 23 ++ .../@stdlib/math/base/special/cexp/src/main.c | 81 ++++++ .../base/special/cexp/test/test.native.js | 270 ++++++++++++++++++ 17 files changed, 1517 insertions(+), 1 deletion(-) create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/benchmark/benchmark.native.js create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/benchmark/c/native/Makefile create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/benchmark/c/native/benchmark.c create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/binding.gyp create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/examples/c/Makefile create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/examples/c/example.c create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/include.gypi create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/include/stdlib/math/base/special/cexp.h create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/lib/native.js create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/manifest.json create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/src/Makefile create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/src/addon.c create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/src/main.c create mode 100644 lib/node_modules/@stdlib/math/base/special/cexp/test/test.native.js diff --git a/lib/node_modules/@stdlib/math/base/special/cexp/README.md b/lib/node_modules/@stdlib/math/base/special/cexp/README.md index 127fa0b27d6e..ed91b9be7e30 100644 --- a/lib/node_modules/@stdlib/math/base/special/cexp/README.md +++ b/lib/node_modules/@stdlib/math/base/special/cexp/README.md @@ -118,6 +118,117 @@ for ( i = 0; i < 100; i++ ) { + + +* * * + +
+ +## C APIs + + + +
+ +
+ + + + + +
+ +### Usage + +```c +#include "stdlib/math/base/special/cexp.h" +``` + +#### stdlib_base_cexp( z ) + +Evaluates the [exponential][exponential-function] function with a double-precision complex floating-point number. + +```c +#include "stdlib/complex/float64.h" +#include "stdlib/complex/real.h" +#include "stdlib/complex/imag.h" + +stdlib_complex128_t z = stdlib_complex128( 0.0, 0.0 ); + +stdlib_complex128_t out = stdlib_base_cexp( z ); + +double re = stdlib_real( out ); +// returns 1.0 + +double im = stdlib_imag( out ); +// returns 0.0 +``` + +The function accepts the following arguments: + +- **z**: `[in] stdlib_complex128_t` input value. + +```c +stdlib_complex128_t stdlib_base_cexp( const stdlib_complex128_t z ); +``` + +
+ + + + + +
+ +
+ + + + + +
+ +### Examples + +```c +#include "stdlib/math/base/special/cexp.h" +#include "stdlib/complex/float64.h" +#include "stdlib/complex/reim.h" +#include + +int main() { + const stdlib_complex128_t x[] = { + stdlib_complex128( 3.14, 1.5 ), + stdlib_complex128( -3.14, -1.5 ), + stdlib_complex128( 0.0, 0.0 ), + stdlib_complex128( 0.0/0.0, 0.0/0.0 ) + }; + + stdlib_complex128_t v; + stdlib_complex128_t y; + double re1; + double im1; + double re2; + double im2; + int i; + for ( i = 0; i < 4; i++ ) { + v = x[ i ]; + y = stdlib_base_cexp( v ); + stdlib_reim( v, &re1, &im1 ); + stdlib_reim( y, &re2, &im2 ); + printf( "cexp(%lf + %lfi) = %lf + %lfi\n", re1, im1, re2, im2 ); + } +} +``` + +
+ + + +
+ + +