diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/README.md b/lib/node_modules/@stdlib/math/base/special/digamma/README.md index d43cc085409c..ab46b4a40f75 100644 --- a/lib/node_modules/@stdlib/math/base/special/digamma/README.md +++ b/lib/node_modules/@stdlib/math/base/special/digamma/README.md @@ -115,6 +115,95 @@ for ( i = 0; i < 10; i++ ) { <!-- /.examples --> +<!-- C interface documentation. --> + +* * * + +<section class="c"> + +## C APIs + +<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. --> + +<section class="intro"> + +</section> + +<!-- /.intro --> + +<!-- C usage documentation. --> + +<section class="usage"> + +### Usage + +```c +#include "stdlib/math/base/special/digamma.h" +``` + +#### digamma( x ) + +Evaluates the [digamma function][digamma-function]. + +```c +double out = digamma( -2.5 ); +// returns ~1.103 + +out = digamma( 1.0 ); +// returns ~-0.577 +``` + +The function accepts the following arguments: + +- **x**: `[in] double` input value. + +```c +double digamma( const double x ); +``` + +</section> + +<!-- /.usage --> + +<!-- C API usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> + +<section class="notes"> + +</section> + +<!-- /.notes --> + +<!-- C API usage examples. --> + +<section class="examples"> + +### Examples + +```c +#include "stdlib/math/base/special/digamma.h" +#include <stdlib.h> +#include <stdio.h> + +int main( void ) { + const double x[] = { 4.0, -1.5, -0.5, 0.5 }; + + double y; + int i; + for ( i = 0; i < 4; i++ ) { + y = stdlib_base_digamma( x[ i ] ); + printf( "digamma(%lf) = %lf\n", x[ i ], y ); + } +} +``` + +</section> + +<!-- /.examples --> + +</section> + +<!-- /.c --> + <!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. --> <section class="related"> diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/benchmark/benchmark.native.js b/lib/node_modules/@stdlib/math/base/special/digamma/benchmark/benchmark.native.js new file mode 100644 index 000000000000..9fe3cde0fe6d --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/benchmark/benchmark.native.js @@ -0,0 +1,61 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 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 resolve = require( 'path' ).resolve; +var bench = require( '@stdlib/bench' ); +var randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var EPS = require( '@stdlib/constants/float64/eps' ); +var tryRequire = require( '@stdlib/utils/try-require' ); +var pkg = require( './../package.json' ).name; + + +// VARIABLES // + +var digamma = tryRequire( resolve( __dirname, './../lib/native.js' ) ); +var opts = { + 'skip': ( digamma instanceof Error ) +}; + + +// MAIN // + +bench( pkg+'::native', opts, function benchmark( b ) { + var x; + var y; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + x = ( randu() * 1000.0 ) + EPS; + y = digamma( x ); + if ( isnan( y ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/benchmark/c/native/Makefile b/lib/node_modules/@stdlib/math/base/special/digamma/benchmark/c/native/Makefile new file mode 100644 index 000000000000..f69e9da2b4d3 --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/benchmark/c/native/Makefile @@ -0,0 +1,146 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2024 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. +#/ + +# VARIABLES # + +ifndef VERBOSE + QUIET := @ +else + QUIET := +endif + +# Determine the OS ([1][1], [2][2]). +# +# [1]: https://en.wikipedia.org/wiki/Uname#Examples +# [2]: http://stackoverflow.com/a/27776822/2225624 +OS ?= $(shell uname) +ifneq (, $(findstring MINGW,$(OS))) + OS := WINNT +else +ifneq (, $(findstring MSYS,$(OS))) + OS := WINNT +else +ifneq (, $(findstring CYGWIN,$(OS))) + OS := WINNT +else +ifneq (, $(findstring Windows_NT,$(OS))) + OS := WINNT +endif +endif +endif +endif + +# Define the program used for compiling C source files: +ifdef C_COMPILER + CC := $(C_COMPILER) +else + CC := gcc +endif + +# Define the command-line options when compiling C files: +CFLAGS ?= \ + -std=c99 \ + -O3 \ + -Wall \ + -pedantic + +# Determine whether to generate position independent code ([1][1], [2][2]). +# +# [1]: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options +# [2]: http://stackoverflow.com/questions/5311515/gcc-fpic-option +ifeq ($(OS), WINNT) + fPIC ?= +else + fPIC ?= -fPIC +endif + +# List of includes (e.g., `-I /foo/bar -I /beep/boop/include`): +INCLUDE ?= + +# List of source files: +SOURCE_FILES ?= + +# List of libraries (e.g., `-lopenblas -lpthread`): +LIBRARIES ?= + +# List of library paths (e.g., `-L /foo/bar -L /beep/boop`): +LIBPATH ?= + +# List of C targets: +c_targets := benchmark.out + + +# RULES # + +#/ +# Compiles source files. +# +# @param {string} [C_COMPILER] - C compiler (e.g., `gcc`) +# @param {string} [CFLAGS] - C compiler options +# @param {(string|void)} [fPIC] - compiler flag determining whether to generate position independent code (e.g., `-fPIC`) +# @param {string} [INCLUDE] - list of includes (e.g., `-I /foo/bar -I /beep/boop/include`) +# @param {string} [SOURCE_FILES] - list of source files +# @param {string} [LIBPATH] - list of library paths (e.g., `-L /foo/bar -L /beep/boop`) +# @param {string} [LIBRARIES] - list of libraries (e.g., `-lopenblas -lpthread`) +# +# @example +# make +# +# @example +# make all +#/ +all: $(c_targets) + +.PHONY: all + +#/ +# Compiles C source files. +# +# @private +# @param {string} CC - C compiler (e.g., `gcc`) +# @param {string} CFLAGS - C compiler options +# @param {(string|void)} fPIC - compiler flag determining whether to generate position independent code (e.g., `-fPIC`) +# @param {string} INCLUDE - list of includes (e.g., `-I /foo/bar`) +# @param {string} SOURCE_FILES - list of source files +# @param {string} LIBPATH - list of library paths (e.g., `-L /foo/bar`) +# @param {string} LIBRARIES - list of libraries (e.g., `-lopenblas`) +#/ +$(c_targets): %.out: %.c + $(QUIET) $(CC) $(CFLAGS) $(fPIC) $(INCLUDE) -o $@ $(SOURCE_FILES) $< $(LIBPATH) -lm $(LIBRARIES) + +#/ +# Runs compiled benchmarks. +# +# @example +# make run +#/ +run: $(c_targets) + $(QUIET) ./$< + +.PHONY: run + +#/ +# Removes generated files. +# +# @example +# make clean +#/ +clean: + $(QUIET) -rm -f *.o *.out + +.PHONY: clean diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/benchmark/c/native/benchmark.c b/lib/node_modules/@stdlib/math/base/special/digamma/benchmark/c/native/benchmark.c new file mode 100644 index 000000000000..153a9508743b --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/benchmark/c/native/benchmark.c @@ -0,0 +1,136 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 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. +*/ + +/** +* Benchmark `digamma`. +*/ +#include "stdlib/math/base/special/digamma.h" +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <time.h> +#include <sys/time.h> + +#define NAME "digamma" +#define ITERATIONS 1000000 +#define REPEATS 3 + +/** +* Prints the TAP version. +*/ +void print_version() { + printf( "TAP version 13\n" ); +} + +/** +* Prints the TAP summary. +* +* @param total total number of tests +* @param passing total number of passing tests +*/ +void print_summary( int total, int passing ) { + printf( "#\n" ); + printf( "1..%d\n", total ); // TAP plan + printf( "# total %d\n", total ); + printf( "# pass %d\n", passing ); + printf( "#\n" ); + printf( "# ok\n" ); +} + +/** +* Prints benchmarks results. +* +* @param elapsed elapsed time in seconds +*/ +void print_results( double elapsed ) { + double rate = (double)ITERATIONS / elapsed; + printf( " ---\n" ); + printf( " iterations: %d\n", ITERATIONS ); + printf( " elapsed: %0.9f\n", elapsed ); + printf( " rate: %0.9f\n", rate ); + printf( " ...\n" ); +} + +/** +* Returns a clock time. +* +* @return clock time +*/ +double tic() { + struct timeval now; + gettimeofday( &now, NULL ); + return (double)now.tv_sec + (double)now.tv_usec / 1.0e6; +} + +/** +* Generates a random number on the interval [0,1]. +* +* @return random number +*/ +double rand_double() { + int r = rand(); + return (double)r / ( (double)RAND_MAX + 1.0 ); +} + +/** +* Runs a benchmark. +* +* @return elapsed time in seconds +*/ +double benchmark() { + double elapsed; + double x; + double y; + double t; + int i; + + t = tic(); + for ( i = 0; i < ITERATIONS; i++ ) { + x = ( 1000.0 * rand_double() ) + 0.1; + y = stdlib_base_digamma( x ); + if ( y != y ) { + printf( "should not return NaN\n" ); + break; + } + } + elapsed = tic() - t; + if ( y != y ) { + printf( "should not return NaN\n" ); + } + return elapsed; +} + +/** +* Main execution sequence. +*/ +int main( void ) { + double elapsed; + int i; + + // Use the current time to seed the random number generator: + srand( time( NULL ) ); + + print_version(); + for ( i = 0; i < REPEATS; i++ ) { + printf( "# c::native::%s\n", NAME ); + elapsed = benchmark(); + print_results( elapsed ); + printf( "ok %d benchmark finished\n", i+1 ); + } + print_summary( REPEATS, REPEATS ); +} diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/binding.gyp b/lib/node_modules/@stdlib/math/base/special/digamma/binding.gyp new file mode 100644 index 000000000000..ec3992233442 --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/binding.gyp @@ -0,0 +1,170 @@ +# @license Apache-2.0 +# +# Copyright (c) 2024 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. + +# A `.gyp` file for building a Node.js native add-on. +# +# [1]: https://gyp.gsrc.io/docs/InputFormatReference.md +# [2]: https://gyp.gsrc.io/docs/UserDocumentation.md +{ + # List of files to include in this file: + 'includes': [ + './include.gypi', + ], + + # Define variables to be used throughout the configuration for all targets: + 'variables': { + # Target name should match the add-on export name: + 'addon_target_name%': 'addon', + + # Set variables based on the host OS: + 'conditions': [ + [ + 'OS=="win"', + { + # Define the object file suffix: + 'obj': 'obj', + }, + { + # Define the object file suffix: + 'obj': 'o', + } + ], # end condition (OS=="win") + ], # end conditions + }, # end variables + + # Define compile targets: + 'targets': [ + + # Target to generate an add-on: + { + # The target name should match the add-on export name: + 'target_name': '<(addon_target_name)', + + # Define dependencies: + 'dependencies': [], + + # Define directories which contain relevant include headers: + 'include_dirs': [ + # Local include directory: + '<@(include_dirs)', + ], + + # List of source files: + 'sources': [ + '<@(src_files)', + ], + + # Settings which should be applied when a target's object files are used as linker input: + 'link_settings': { + # Define libraries: + 'libraries': [ + '<@(libraries)', + ], + + # Define library directories: + 'library_dirs': [ + '<@(library_dirs)', + ], + }, + + # C/C++ compiler flags: + 'cflags': [ + # Enable commonly used warning options: + '-Wall', + + # Aggressive optimization: + '-O3', + ], + + # C specific compiler flags: + 'cflags_c': [ + # Specify the C standard to which a program is expected to conform: + '-std=c99', + ], + + # C++ specific compiler flags: + 'cflags_cpp': [ + # Specify the C++ standard to which a program is expected to conform: + '-std=c++11', + ], + + # Linker flags: + 'ldflags': [], + + # Apply conditions based on the host OS: + 'conditions': [ + [ + 'OS=="mac"', + { + # Linker flags: + 'ldflags': [ + '-undefined dynamic_lookup', + '-Wl,-no-pie', + '-Wl,-search_paths_first', + ], + }, + ], # end condition (OS=="mac") + [ + 'OS!="win"', + { + # C/C++ flags: + 'cflags': [ + # Generate platform-independent code: + '-fPIC', + ], + }, + ], # end condition (OS!="win") + ], # end conditions + }, # end target <(addon_target_name) + + # Target to copy a generated add-on to a standard location: + { + 'target_name': 'copy_addon', + + # Declare that the output of this target is not linked: + 'type': 'none', + + # Define dependencies: + 'dependencies': [ + # Require that the add-on be generated before building this target: + '<(addon_target_name)', + ], + + # Define a list of actions: + 'actions': [ + { + 'action_name': 'copy_addon', + 'message': 'Copying addon...', + + # Explicitly list the inputs in the command-line invocation below: + 'inputs': [], + + # Declare the expected outputs: + 'outputs': [ + '<(addon_output_dir)/<(addon_target_name).node', + ], + + # Define the command-line invocation: + 'action': [ + 'cp', + '<(PRODUCT_DIR)/<(addon_target_name).node', + '<(addon_output_dir)/<(addon_target_name).node', + ], + }, + ], # end actions + }, # end target copy_addon + ], # end targets +} diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/examples/c/Makefile b/lib/node_modules/@stdlib/math/base/special/digamma/examples/c/Makefile new file mode 100644 index 000000000000..6aed70daf167 --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/examples/c/Makefile @@ -0,0 +1,146 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2024 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. +#/ + +# VARIABLES # + +ifndef VERBOSE + QUIET := @ +else + QUIET := +endif + +# Determine the OS ([1][1], [2][2]). +# +# [1]: https://en.wikipedia.org/wiki/Uname#Examples +# [2]: http://stackoverflow.com/a/27776822/2225624 +OS ?= $(shell uname) +ifneq (, $(findstring MINGW,$(OS))) + OS := WINNT +else +ifneq (, $(findstring MSYS,$(OS))) + OS := WINNT +else +ifneq (, $(findstring CYGWIN,$(OS))) + OS := WINNT +else +ifneq (, $(findstring Windows_NT,$(OS))) + OS := WINNT +endif +endif +endif +endif + +# Define the program used for compiling C source files: +ifdef C_COMPILER + CC := $(C_COMPILER) +else + CC := gcc +endif + +# Define the command-line options when compiling C files: +CFLAGS ?= \ + -std=c99 \ + -O3 \ + -Wall \ + -pedantic + +# Determine whether to generate position independent code ([1][1], [2][2]). +# +# [1]: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options +# [2]: http://stackoverflow.com/questions/5311515/gcc-fpic-option +ifeq ($(OS), WINNT) + fPIC ?= +else + fPIC ?= -fPIC +endif + +# List of includes (e.g., `-I /foo/bar -I /beep/boop/include`): +INCLUDE ?= + +# List of source files: +SOURCE_FILES ?= + +# List of libraries (e.g., `-lopenblas -lpthread`): +LIBRARIES ?= + +# List of library paths (e.g., `-L /foo/bar -L /beep/boop`): +LIBPATH ?= + +# List of C targets: +c_targets := example.out + + +# RULES # + +#/ +# Compiles source files. +# +# @param {string} [C_COMPILER] - C compiler (e.g., `gcc`) +# @param {string} [CFLAGS] - C compiler options +# @param {(string|void)} [fPIC] - compiler flag determining whether to generate position independent code (e.g., `-fPIC`) +# @param {string} [INCLUDE] - list of includes (e.g., `-I /foo/bar -I /beep/boop/include`) +# @param {string} [SOURCE_FILES] - list of source files +# @param {string} [LIBPATH] - list of library paths (e.g., `-L /foo/bar -L /beep/boop`) +# @param {string} [LIBRARIES] - list of libraries (e.g., `-lopenblas -lpthread`) +# +# @example +# make +# +# @example +# make all +#/ +all: $(c_targets) + +.PHONY: all + +#/ +# Compiles C source files. +# +# @private +# @param {string} CC - C compiler (e.g., `gcc`) +# @param {string} CFLAGS - C compiler options +# @param {(string|void)} fPIC - compiler flag determining whether to generate position independent code (e.g., `-fPIC`) +# @param {string} INCLUDE - list of includes (e.g., `-I /foo/bar`) +# @param {string} SOURCE_FILES - list of source files +# @param {string} LIBPATH - list of library paths (e.g., `-L /foo/bar`) +# @param {string} LIBRARIES - list of libraries (e.g., `-lopenblas`) +#/ +$(c_targets): %.out: %.c + $(QUIET) $(CC) $(CFLAGS) $(fPIC) $(INCLUDE) -o $@ $(SOURCE_FILES) $< $(LIBPATH) -lm $(LIBRARIES) + +#/ +# Runs compiled examples. +# +# @example +# make run +#/ +run: $(c_targets) + $(QUIET) ./$< + +.PHONY: run + +#/ +# Removes generated files. +# +# @example +# make clean +#/ +clean: + $(QUIET) -rm -f *.o *.out + +.PHONY: clean diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/examples/c/example.c b/lib/node_modules/@stdlib/math/base/special/digamma/examples/c/example.c new file mode 100644 index 000000000000..6b8aa919dbf6 --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/examples/c/example.c @@ -0,0 +1,31 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 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. +*/ + +#include "stdlib/math/base/special/digamma.h" +#include <stdio.h> + +int main( void ) { + const double x[] = { 4.0, -1.5, -0.5, 0.5 }; + + double y; + int i; + for ( i = 0; i < 4; i++ ) { + y = stdlib_base_digamma( x[ i ] ); + printf( "digamma(%lf) = %lf\n", x[ i ], y ); + } +} diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/include.gypi b/lib/node_modules/@stdlib/math/base/special/digamma/include.gypi new file mode 100644 index 000000000000..575cb043c0bf --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/include.gypi @@ -0,0 +1,53 @@ +# @license Apache-2.0 +# +# Copyright (c) 2024 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. + +# A GYP include file for building a Node.js native add-on. +# +# Main documentation: +# +# [1]: https://gyp.gsrc.io/docs/InputFormatReference.md +# [2]: https://gyp.gsrc.io/docs/UserDocumentation.md +{ + # Define variables to be used throughout the configuration for all targets: + 'variables': { + # Source directory: + 'src_dir': './src', + + # Include directories: + 'include_dirs': [ + '<!@(node -e "var arr = require(\'@stdlib/utils/library-manifest\')(\'./manifest.json\',{},{\'basedir\':process.cwd(),\'paths\':\'posix\'}).include; for ( var i = 0; i < arr.length; i++ ) { console.log( arr[ i ] ); }")', + ], + + # Add-on destination directory: + 'addon_output_dir': './src', + + # Source files: + 'src_files': [ + '<(src_dir)/addon.c', + '<!@(node -e "var arr = require(\'@stdlib/utils/library-manifest\')(\'./manifest.json\',{},{\'basedir\':process.cwd(),\'paths\':\'posix\'}).src; for ( var i = 0; i < arr.length; i++ ) { console.log( arr[ i ] ); }")', + ], + + # Library dependencies: + 'libraries': [ + '<!@(node -e "var arr = require(\'@stdlib/utils/library-manifest\')(\'./manifest.json\',{},{\'basedir\':process.cwd(),\'paths\':\'posix\'}).libraries; for ( var i = 0; i < arr.length; i++ ) { console.log( arr[ i ] ); }")', + ], + + # Library directories: + 'library_dirs': [ + '<!@(node -e "var arr = require(\'@stdlib/utils/library-manifest\')(\'./manifest.json\',{},{\'basedir\':process.cwd(),\'paths\':\'posix\'}).libpath; for ( var i = 0; i < arr.length; i++ ) { console.log( arr[ i ] ); }")', + ], + }, # end variables +} diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/include/stdlib/math/base/special/digamma.h b/lib/node_modules/@stdlib/math/base/special/digamma/include/stdlib/math/base/special/digamma.h new file mode 100644 index 000000000000..dc1a991b3371 --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/include/stdlib/math/base/special/digamma.h @@ -0,0 +1,41 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 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. +*/ + +/** +* Header file containing function declarations. +*/ +#ifndef STDLIB_MATH_BASE_SPECIAL_DIGAMMA_H +#define STDLIB_MATH_BASE_SPECIAL_DIGAMMA_H + +/* +* If C++, prevent name mangling so that the compiler emits a binary file having undecorated names, thus mirroring the behavior of a C compiler. +*/ +#ifdef __cplusplus +extern "C" { +#endif + +/** +* Evaluates the digamma function. +*/ +double stdlib_base_digamma( const double x ); + +#ifdef __cplusplus +} +#endif + +#endif // !STDLIB_MATH_BASE_SPECIAL_DIGAMMA_H diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/lib/native.js b/lib/node_modules/@stdlib/math/base/special/digamma/lib/native.js new file mode 100644 index 000000000000..c951161adec8 --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/lib/native.js @@ -0,0 +1,62 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 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 addon = require( './../src/addon.node' ); + + +// MAIN // + +/** +* Evaluates the digamma function. +* +* @private +* @param {number} x - input value +* @returns {number} function value +* +* @example +* var v = digamma( -2.5 ); +* // returns ~1.103 +* +* @example +* var v = digamma( 1.0 ); +* // returns ~-0.577 +* +* @example +* var v = digamma( 10.0 ); +* // returns ~2.252 +* +* @example +* var v = digamma( NaN ); +* // returns NaN +* +* @example +* var v = digamma( -1.0 ); +* // returns NaN +*/ +function digamma( x ) { + return addon( x ); +} + + +// EXPORTS // + +module.exports = digamma; diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/lib/polyval_p.js b/lib/node_modules/@stdlib/math/base/special/digamma/lib/polyval_p.js index feb7410cdb8f..ed6587a0c30f 100644 --- a/lib/node_modules/@stdlib/math/base/special/digamma/lib/polyval_p.js +++ b/lib/node_modules/@stdlib/math/base/special/digamma/lib/polyval_p.js @@ -1,7 +1,7 @@ /** * @license Apache-2.0 * -* Copyright (c) 2022 The Stdlib Authors. +* Copyright (c) 2024 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. diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/lib/rational_pq.js b/lib/node_modules/@stdlib/math/base/special/digamma/lib/rational_pq.js index a617c1478905..0399aa5f9526 100644 --- a/lib/node_modules/@stdlib/math/base/special/digamma/lib/rational_pq.js +++ b/lib/node_modules/@stdlib/math/base/special/digamma/lib/rational_pq.js @@ -1,7 +1,7 @@ /** * @license Apache-2.0 * -* Copyright (c) 2022 The Stdlib Authors. +* Copyright (c) 2024 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. @@ -22,7 +22,7 @@ // MAIN // /** -* Evaluates a rational function, i.e., the ratio of two polynomials described by the coefficients stored in \\(P\\) and \\(Q\\). +* Evaluates a rational function (i.e., the ratio of two polynomials described by the coefficients stored in \\(P\\) and \\(Q\\)). * * ## Notes * diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/manifest.json b/lib/node_modules/@stdlib/math/base/special/digamma/manifest.json new file mode 100644 index 000000000000..0c5beadfe963 --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/manifest.json @@ -0,0 +1,85 @@ +{ + "options": { + "task": "build" + }, + "fields": [ + { + "field": "src", + "resolve": true, + "relative": true + }, + { + "field": "include", + "resolve": true, + "relative": true + }, + { + "field": "libraries", + "resolve": false, + "relative": false + }, + { + "field": "libpath", + "resolve": true, + "relative": false + } + ], + "confs": [ + { + "task": "build", + "src": [ + "./src/main.c" + ], + "include": [ + "./include" + ], + "libraries": [], + "libpath": [], + "dependencies": [ + "@stdlib/math/base/napi/unary", + "@stdlib/math/base/assert/is-nan", + "@stdlib/math/base/special/floor", + "@stdlib/math/base/special/tan", + "@stdlib/math/base/special/ln", + "@stdlib/constants/float64/pi" + ] + }, + { + "task": "benchmark", + "src": [ + "./src/main.c" + ], + "include": [ + "./include" + ], + "libraries": [], + "libpath": [], + "dependencies": [ + "@stdlib/math/base/assert/is-nan", + "@stdlib/math/base/special/floor", + "@stdlib/math/base/special/tan", + "@stdlib/math/base/special/ln", + "@stdlib/constants/float64/pi" + ] + }, + { + "task": "examples", + "src": [ + "./src/main.c" + ], + "include": [ + "./include" + ], + "libraries": [], + "libpath": [], + "dependencies": [ + "@stdlib/math/base/assert/is-nan", + "@stdlib/math/base/special/floor", + "@stdlib/math/base/special/tan", + "@stdlib/math/base/special/ln", + "@stdlib/constants/float64/pi" + ] + } + ] +} + diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/scripts/evalpoly.js b/lib/node_modules/@stdlib/math/base/special/digamma/scripts/evalpoly.js index 4a70779d67d5..9afd83e1562b 100644 --- a/lib/node_modules/@stdlib/math/base/special/digamma/scripts/evalpoly.js +++ b/lib/node_modules/@stdlib/math/base/special/digamma/scripts/evalpoly.js @@ -24,10 +24,15 @@ // MODULES // var resolve = require( 'path' ).resolve; +var readFileSync = require( '@stdlib/fs/read-file' ).sync; var writeFileSync = require( '@stdlib/fs/write-file' ).sync; var currentYear = require( '@stdlib/time/current-year' ); +var substringBefore = require( '@stdlib/string/substring-before' ); +var substringAfter = require( '@stdlib/string/substring-after' ); +var format = require( '@stdlib/string/format' ); var licenseHeader = require( '@stdlib/_tools/licenses/header' ); var compile = require( '@stdlib/math/base/tools/evalpoly-compile' ); +var compileC = require( '@stdlib/math/base/tools/evalpoly-compile-c' ); // VARIABLES // @@ -52,6 +57,33 @@ var header = licenseHeader( 'Apache-2.0', 'js', { header += '\n/* This is a generated file. Do not edit directly. */\n'; +// FUNCTIONS // + +/** +* Inserts a compiled function into file content. +* +* @private +* @param {string} text - source content +* @param {string} id - function identifier +* @param {string} str - function string +* @returns {string} updated content +*/ +function insert( text, id, str ) { + var before; + var after; + var begin; + var end; + + begin = '// BEGIN: '+id; + end = '// END: '+id; + + before = substringBefore( text, begin ); + after = substringAfter( text, end ); + + return format( '%s// BEGIN: %s\n\n%s\n%s%s', before, id, str, end, after ); +} + + // MAIN // /** @@ -61,7 +93,9 @@ header += '\n/* This is a generated file. Do not edit directly. */\n'; */ function main() { var fpath; + var copts; var opts; + var file; var str; opts = { @@ -71,6 +105,20 @@ function main() { fpath = resolve( __dirname, '..', 'lib', 'polyval_p.js' ); str = header + compile( P ); writeFileSync( fpath, str, opts ); + + copts = { + 'dtype': 'double', + 'name': '' + }; + + fpath = resolve( __dirname, '..', 'src', 'main.c' ); + file = readFileSync( fpath, opts ); + + copts.name = 'polyval_p'; + str = compileC( P, copts ); + file = insert( file, copts.name, str ); + + writeFileSync( fpath, file, opts ); } main(); diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/scripts/evalrational.js b/lib/node_modules/@stdlib/math/base/special/digamma/scripts/evalrational.js index c41de3f12fe8..d91386b086df 100644 --- a/lib/node_modules/@stdlib/math/base/special/digamma/scripts/evalrational.js +++ b/lib/node_modules/@stdlib/math/base/special/digamma/scripts/evalrational.js @@ -24,10 +24,15 @@ // MODULES // var resolve = require( 'path' ).resolve; +var readFileSync = require( '@stdlib/fs/read-file' ).sync; var writeFileSync = require( '@stdlib/fs/write-file' ).sync; var currentYear = require( '@stdlib/time/current-year' ); var licenseHeader = require( '@stdlib/_tools/licenses/header' ); var compile = require( '@stdlib/math/base/tools/evalrational-compile' ); +var compileC = require( '@stdlib/math/base/tools/evalrational-compile-c' ); +var substringBefore = require( '@stdlib/string/substring-before' ); +var substringAfter = require( '@stdlib/string/substring-after' ); +var format = require( '@stdlib/string/format' ); // VARIABLES // @@ -60,6 +65,33 @@ var header = licenseHeader( 'Apache-2.0', 'js', { header += '\n/* This is a generated file. Do not edit directly. */\n'; +// FUNCTIONS // + +/** +* Inserts a compiled function into file content. +* +* @private +* @param {string} text - source content +* @param {string} id - function identifier +* @param {string} str - function string +* @returns {string} updated content +*/ +function insert( text, id, str ) { + var before; + var after; + var begin; + var end; + + begin = '// BEGIN: '+id; + end = '// END: '+id; + + before = substringBefore( text, begin ); + after = substringAfter( text, end ); + + return format( '%s// BEGIN: %s\n\n%s\n%s%s', before, id, str, end, after ); +} + + // MAIN // /** @@ -69,7 +101,9 @@ header += '\n/* This is a generated file. Do not edit directly. */\n'; */ function main() { var fpath; + var copts; var opts; + var file; var str; opts = { @@ -79,6 +113,20 @@ function main() { fpath = resolve( __dirname, '..', 'lib', 'rational_pq.js' ); str = header + compile( P, Q ); writeFileSync( fpath, str, opts ); + + copts = { + 'dtype': 'double', + 'name': 'rational_pq' + }; + + fpath = resolve( __dirname, '..', 'src', 'main.c' ); + file = readFileSync( fpath, opts ); + + copts.name = 'rational_pq'; + str = compileC( P, Q, copts ); + file = insert( file, copts.name, str ); + + writeFileSync( fpath, file, opts ); } main(); diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/src/Makefile b/lib/node_modules/@stdlib/math/base/special/digamma/src/Makefile new file mode 100644 index 000000000000..bcf18aa46655 --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/src/Makefile @@ -0,0 +1,70 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2024 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. +#/ + +# VARIABLES # + +ifndef VERBOSE + QUIET := @ +else + QUIET := +endif + +# Determine the OS ([1][1], [2][2]). +# +# [1]: https://en.wikipedia.org/wiki/Uname#Examples +# [2]: http://stackoverflow.com/a/27776822/2225624 +OS ?= $(shell uname) +ifneq (, $(findstring MINGW,$(OS))) + OS := WINNT +else +ifneq (, $(findstring MSYS,$(OS))) + OS := WINNT +else +ifneq (, $(findstring CYGWIN,$(OS))) + OS := WINNT +else +ifneq (, $(findstring Windows_NT,$(OS))) + OS := WINNT +endif +endif +endif +endif + + +# RULES # + +#/ +# Removes generated files for building an add-on. +# +# @example +# make clean-addon +#/ +clean-addon: + $(QUIET) -rm -f *.o *.node + +.PHONY: clean-addon + +#/ +# Removes generated files. +# +# @example +# make clean +#/ +clean: clean-addon + +.PHONY: clean diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/src/addon.c b/lib/node_modules/@stdlib/math/base/special/digamma/src/addon.c new file mode 100644 index 000000000000..06efba18df51 --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/src/addon.c @@ -0,0 +1,23 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 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. +*/ + +#include "stdlib/math/base/special/digamma.h" +#include "stdlib/math/base/napi/unary.h" + +// cppcheck-suppress shadowFunction +STDLIB_MATH_BASE_NAPI_MODULE_D_D( stdlib_base_digamma ) diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/src/main.c b/lib/node_modules/@stdlib/math/base/special/digamma/src/main.c new file mode 100644 index 000000000000..bd1ed84759f6 --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/src/main.c @@ -0,0 +1,269 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 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. +* +* +* ## Notice +* +* The original C++ code and copyright notice are from the [Boost library]{@link http://www.boost.org/doc/libs/1_53_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/sf_gamma/digamma.html}. The implementation follows the original but has been modified for JavaScript. +* +* ```text +* (C) Copyright John Maddock 2006. +* +* Use, modification and distribution are subject to the +* Boost Software License, Version 1.0. (See accompanying file +* LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +* ``` +*/ + +#include "stdlib/math/base/special/digamma.h" +#include "stdlib/math/base/assert/is_nan.h" +#include "stdlib/math/base/special/floor.h" +#include "stdlib/math/base/special/tan.h" +#include "stdlib/math/base/special/ln.h" +#include "stdlib/constants/float64/pi.h" + +static const double MIN_SAFE_ASYMPTOTIC = 10.0; // BIG! +static const double root1 = 1569415565.0 / 1073741824.0; +static const double root2 = ( 381566830.0 / 1073741824.0 ) / 1073741824.0; +static const double root3 = 0.9016312093258695918615325266959189453125e-19; +static const double Y = 0.99558162689208984; + +/* Begin auto-generated functions. The following functions are auto-generated. Do not edit directly. */ + +// BEGIN: polyval_p + +/** +* Evaluates a polynomial. +* +* ## Notes +* +* - The implementation uses [Horner's rule][horners-method] for efficient computation. +* +* [horners-method]: https://en.wikipedia.org/wiki/Horner%27s_method +* +* @param x value at which to evaluate the polynomial +* @return evaluated polynomial +*/ +static double polyval_p( const double x ) { + return 0.08333333333333333 + (x * (-0.008333333333333333 + (x * (0.003968253968253968 + (x * (-0.004166666666666667 + (x * (0.007575757575757576 + (x * (-0.021092796092796094 + (x * (0.08333333333333333 + (x * -0.4432598039215686))))))))))))); +} + +// END: polyval_p// BEGIN: rational_pq + +/** +* Evaluates a rational function (i.e., the ratio of two polynomials described by the coefficients stored in \\(P\\) and \\(Q\\)). +* +* ## Notes +* +* - Coefficients should be sorted in ascending degree. +* - The implementation uses [Horner's rule][horners-method] for efficient computation. +* +* [horners-method]: https://en.wikipedia.org/wiki/Horner%27s_method +* +* @param x value at which to evaluate the rational function +* @return evaluated rational function +*/ +static double rational_pq( const double x ) { + double ax; + double ix; + double s1; + double s2; + if ( x == 0.0 ) { + return 0.25479851061131553; + } + if ( x < 0.0 ) { + ax = -x; + } else { + ax = x; + } + if ( ax <= 1.0 ) { + s1 = 0.25479851061131553 + (x * (-0.3255503118680449 + (x * (-0.6503185377089651 + (x * (-0.28919126444774784 + (x * (-0.04525132144873906 + (x * (-0.002071332116774595 + (x * 0.0))))))))))); + s2 = 1.0 + (x * (2.076711702373047 + (x * (1.4606242909763516 + (x * (0.43593529692665967 + (x * (0.054151797245674226 + (x * (0.0021284987017821146 + (x * -5.578984132167551e-7))))))))))); + } else { + ix = 1.0 / x; + s1 = 0.0 + (ix * (-0.002071332116774595 + (ix * (-0.04525132144873906 + (ix * (-0.28919126444774784 + (ix * (-0.6503185377089651 + (ix * (-0.3255503118680449 + (ix * 0.25479851061131553))))))))))); + s2 = -5.578984132167551e-7 + (ix * (0.0021284987017821146 + (ix * (0.054151797245674226 + (ix * (0.43593529692665967 + (ix * (1.4606242909763516 + (ix * (2.076711702373047 + (ix * 1.0))))))))))); + } + return s1 / s2; +} + +// END: rational_pq + +/* End auto-generated functions. */ + +/** +* Evaluates the digamma function via asymptotic expansion. +* +* @param x input value +* @returns function value +*/ +double asymptoticApprox( const double x ) { + double y; + double z; + double xc; + + xc = x; + xc -= 1.0; + y = stdlib_base_ln( xc ) + ( 1.0 / ( 2.0 * xc ) ); + z = 1.0 / ( xc * xc ); + return y - ( z * polyval_p( z ) ); +} + +/** +* Evaluates the digamma function over interval `[1,2]`. +* +* @param x input value +* @returns function value +*/ +double rationalApprox( const double x ) { + double g; + double r; + + g = x - root1; + g -= root2; + g -= root3; + r = rational_pq( x - 1.0 ); + return ( g * Y ) + ( g * r ); +} + +/** +* Evaluates the digamma function. +* +* ## Method +* +* 1. For \\(x < 0\\), we use the reflection formula +* +* ```tex +* \psi(1-x) = \psi(x) + \frac{\pi}{\tan(\pi x)} +* ``` +* +* to make \\(x\\) positive. +* +* 2. For \\(x \in \[0,1]\\), we use the recurrence relation +* +* ```tex +* \psi(x) = \psi(x+1) - \frac{1}{x} +* ``` +* +* to shift the evaluation range to \\(\[1,2]\\). +* +* 3. For \\(x \in \[1,2]\\), we use a rational approximation of the form +* +* ```tex +* \psi(x) = (x - \mathrm{root})(Y + \operatorname{R}(x-1)) +* ``` +* +* where \\(\mathrm{root}\\) is the location of the positive root of \\(\psi\\), \\(Y\\) is a constant, and \\(R\\) is optimized for low absolute error compared to \\(Y\\). +* +* <!-- <note>--> +* +* Note that, since \\(\mathrm{root}\\) is irrational, we need twice as many digits in \\(\mathrm{root}\\) as in \\(x\\) in order to avoid cancellation error during subtraction, assuming \\(x\\) has an exact value. This means that, even if \\(x\\) is rounded to the next representable value, the result of \\(\psi(x)\\) will not be zero. +* +* <!-- </note> --> +* +* <!-- <note> --> +* +* This approach gives 17-digit precision. +* +* <!-- </note> --> +* +* 4. For \\(x \in \[2,\mathrm{BIG}]\\), we use the recurrence relation +* +* ```tex +* \psi(x+1) = \psi(x) + \frac{1}{x} +* ``` +* +* to shift the evaluation range to \\(\[1,2]\\). +* +* 5. For \\(x > \mathrm{BIG}\\), we use the asymptotic expression +* +* ```tex +* \psi(x) = \ln(x) + \frac{1}{2x} - \biggl( \frac{B_{21}}{2x^2} + \frac{B_{22}}{4x^4} + \frac{B_{23}}{6x^6} + \ldots \biggr) +* ``` +* +* This expansion, however, is divergent after a few terms. The number of terms depends on \\(x\\). Accordingly, we must choose a value of \\(\mathrm{BIG}\\) which allows us to truncate the series at a term that is too small to have an effect on the result. Setting \\(\mathrm{BIG} = 10\\), allows us to truncate the series early and evaluate as \\(1/x^2\\). +* +* <!-- <note> --> +* +* This approach gives 17-digit precision for \\(x \geq 10\\). +* +* <!-- </note> --> +* +* ## Notes +* +* - Maximum deviation found: \\(1.466\\mbox{e-}18\\) +* - Max error found: \\(2.452\mbox{e-}17\\) (double precision) +* +* @param x input value +* @returns function value +* +* @example +* double v = stdlib_base_digamma( -2.5 ); +* // returns ~1.103 +*/ +double stdlib_base_digamma( const double x ) { + double rem; + double tmp; + double xc; + + if ( stdlib_base_is_nan( x ) || x == 0.0 ) { + return 0.0 / 0.0; // NaN + } + + // If `x` is negative, use reflection... + xc = x; + if ( xc <= -1.0 ) { + // Reflect: + xc = 1.0 - xc; + + // Argument reduction for tan: + rem = xc - stdlib_base_floor( xc ); + + // Shift to negative if > 0.5: + if ( rem > 0.5 ) { + rem -= 1.0; + } + + // Check for evaluation at a negative pole: + if ( rem == 0.0 ) { + return 0.0 / 0.0; // NaN + } + tmp = STDLIB_CONSTANT_FLOAT64_PI / stdlib_base_tan( STDLIB_CONSTANT_FLOAT64_PI * rem ); + } else { + tmp = 0.0; + } + + // If we're above the lower-limit for the asymptotic expansion, then use it... + if ( xc >= MIN_SAFE_ASYMPTOTIC ) { + tmp += asymptoticApprox( xc ); + return tmp; + } + + // If x > 2, reduce to the interval [1,2]... + while ( xc > 2.0 ) { + xc -= 1.0; + tmp += 1.0 / xc; + } + + // If x < 1, use recurrence to shift to > 1.. + while ( xc < 1.0 ) { + tmp -= 1.0 / xc; + xc += 1.0; + } + tmp += rationalApprox( xc ); + return tmp; +} diff --git a/lib/node_modules/@stdlib/math/base/special/digamma/test/test.native.js b/lib/node_modules/@stdlib/math/base/special/digamma/test/test.native.js new file mode 100644 index 000000000000..f7d0c06157f3 --- /dev/null +++ b/lib/node_modules/@stdlib/math/base/special/digamma/test/test.native.js @@ -0,0 +1,110 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 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 resolve = require( 'path' ).resolve; +var tape = require( 'tape' ); +var isfinite = require( '@stdlib/math/base/assert/is-finite' ); +var isnan = require( '@stdlib/assert/is-nan' ); +var abs = require( '@stdlib/math/base/special/abs' ); +var PINF = require( '@stdlib/constants/float64/pinf' ); +var tryRequire = require( '@stdlib/utils/try-require' ); + + +// VARIABLES // + +var digamma = tryRequire( resolve( __dirname, './../lib/native.js' ) ); +var opts = { + 'skip': ( digamma instanceof Error ) +}; + + +// FIXTURES // + +var data = require( './fixtures/r/data.json' ); +var expected = require( './fixtures/r/expected.json' ); +var v; +var i; +for ( i = 0; i < expected.length; i++ ) { + v = expected[ i ]; + if ( v === 'Inf' ) { + expected[ i ] = PINF; + } + else if ( v === 'NaN' ) { + expected[ i ] = NaN; + } +} + + +// TESTS // + +tape( 'main export is a function', opts, function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof digamma, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function returns `NaN` if provided a `NaN`', opts, function test( t ) { + var val = digamma( NaN ); + t.equal( isnan( val ), true, 'returns expected value' ); + t.end(); +}); + +tape( 'the function returns `NaN` if provided `0`', opts, function test( t ) { + var val = digamma( 0.0 ); + t.equal( isnan( val ), true, 'returns expected value' ); + t.end(); +}); + +tape( 'the function evaluates the digamma function', opts, function test( t ) { + var actual; + var b1; + var b2; + var i; + for ( i = 0; i < data.length; i++ ) { + actual = digamma( data[ i ] ); + + b1 = isfinite( actual ); + b2 = isfinite( expected[ i ] ); + t.equal( b1, b2, 'returned result is ' + ( (b2) ? 'finite' : 'not finite' ) ); + + b1 = isnan( actual ); + b2 = isnan( expected[ i ] ); + t.equal( b1, b2, 'returned result is ' + ( (b1) ? '' : 'not' ) + ' NaN' ); + if ( !b1 ) { + t.ok( abs( actual - expected[ i ] ) < 1.0e-14, 'returned result is within tolerance. actual: ' + actual + '; expected: ' + expected[ i ] + '.' ); + } + } + t.end(); +}); + +tape( 'the function evaluates the digamma function for `x` such that remainder > 0.5', opts, function test( t ) { + var expected; + var actual; + var x; + + x = -3.8; + expected = -2.863183589156929; + actual = digamma( x ); + + t.ok( abs( actual - expected ) < 1.0e-14, 'returned result within tolerance' ); + t.end(); +});