From 2477b905d23e8a02d652571cc26f9d3444573053 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Fri, 2 Oct 2026 18:29:13 +0200 Subject: [PATCH] feat: add C implementation for blas/ext/base/ndarray/dcusumkbn Add the ndarray adapter and optional native bridge while preserving the adopted compensated prefix semantics and JavaScript fallback. Cover exact cancellation prefixes, aliases, scalar read order and configured integer widths. Assisted-by: OpenAI Codex --- .../blas/ext/base/ndarray/dcusumkbn/README.md | 167 ++++++++ .../dcusumkbn/benchmark/benchmark.native.js | 111 +++++ .../ndarray/dcusumkbn/benchmark/c/Makefile | 146 +++++++ .../ndarray/dcusumkbn/benchmark/c/benchmark.c | 152 +++++++ .../ext/base/ndarray/dcusumkbn/binding.gyp | 267 ++++++++++++ .../ndarray/dcusumkbn/examples/c/Makefile | 146 +++++++ .../ndarray/dcusumkbn/examples/c/example.c | 81 ++++ .../ext/base/ndarray/dcusumkbn/include.gypi | 53 +++ .../stdlib/blas/ext/base/ndarray/dcusumkbn.h | 42 ++ .../ndarray/dcusumkbn/lib/can_use_native.js | 73 ++++ .../ext/base/ndarray/dcusumkbn/lib/index.js | 8 +- .../ext/base/ndarray/dcusumkbn/lib/native.js | 100 +++++ .../ext/base/ndarray/dcusumkbn/manifest.json | 111 +++++ .../ext/base/ndarray/dcusumkbn/package.json | 8 +- .../ext/base/ndarray/dcusumkbn/src/Makefile | 70 ++++ .../ext/base/ndarray/dcusumkbn/src/addon.c | 126 ++++++ .../ext/base/ndarray/dcusumkbn/src/main.c | 92 ++++ .../test/fixtures/exact-prefixes.json | 395 ++++++++++++++++++ .../ndarray/dcusumkbn/test/test.native.js | 253 +++++++++++ 19 files changed, 2398 insertions(+), 3 deletions(-) create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/benchmark/benchmark.native.js create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/benchmark/c/Makefile create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/benchmark/c/benchmark.c create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/binding.gyp create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/examples/c/Makefile create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/examples/c/example.c create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/include.gypi create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/include/stdlib/blas/ext/base/ndarray/dcusumkbn.h create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/lib/can_use_native.js create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/lib/native.js create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/manifest.json create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/src/Makefile create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/src/addon.c create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/src/main.c create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/test/fixtures/exact-prefixes.json create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/test/test.native.js diff --git a/lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/README.md b/lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/README.md index 34e940b0cbc5..5071903dce2a 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/README.md +++ b/lib/node_modules/@stdlib/blas/ext/base/ndarray/dcusumkbn/README.md @@ -123,6 +123,173 @@ console.log( ndarray2array( v ) ); + + +* * * + +
+ +## C APIs + +
+ +
+ + + +
+ +### Usage + +```c +#include "stdlib/blas/ext/base/ndarray/dcusumkbn.h" +``` + +#### stdlib_blas_ext_dcusumkbn( arrays ) + +Computes the cumulative sum of a one-dimensional double-precision floating-point ndarray using an improved Kahan–Babuška algorithm. + +```c +#include "stdlib/ndarray/ctor.h" +#include "stdlib/ndarray/dtypes.h" +#include "stdlib/ndarray/index_modes.h" +#include "stdlib/ndarray/orders.h" +#include "stdlib/ndarray/base/bytes_per_element.h" +#include + +// Create one-dimensional input and output ndarrays: +const double dataX[] = { 1.0e16, 1.0, -1.0e16 }; +double dataY[] = { 0.0, 0.0, 0.0 }; +int64_t shape[] = { 3 }; +int64_t strides[] = { STDLIB_NDARRAY_FLOAT64_BYTES_PER_ELEMENT }; +int8_t submodes[] = { STDLIB_NDARRAY_INDEX_ERROR }; + +struct ndarray *x = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT64, (uint8_t *)dataX, 1, shape, strides, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 1, submodes ); +struct ndarray *y = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT64, (uint8_t *)dataY, 1, shape, strides, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 1, submodes ); + +// Create a zero-dimensional ndarray containing the initial sum: +const double dataInitial[] = { 0.0 }; +int64_t scalarStrides[] = { 0 }; +struct ndarray *initial = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT64, (uint8_t *)dataInitial, 0, NULL, scalarStrides, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 1, submodes ); + +// Perform computation: +const struct ndarray *arrays[] = { x, y, initial }; +stdlib_blas_ext_dcusumkbn( arrays ); +// dataY => { 1.0e16, 1.0e16, 1.0 } + +// Free allocated memory: +stdlib_ndarray_free( x ); +stdlib_ndarray_free( y ); +stdlib_ndarray_free( initial ); +``` + +The function accepts the following arguments: + +- **arrays**: `[in] const struct ndarray**` list containing the following ndarrays: + + - `[in] const struct ndarray*` a one-dimensional double-precision floating-point input ndarray. + - `[out] const struct ndarray*` a one-dimensional double-precision floating-point output ndarray. + - `[in] const struct ndarray*` a zero-dimensional double-precision floating-point ndarray containing the initial sum. + +```c +void stdlib_blas_ext_dcusumkbn( const struct ndarray *arrays[] ); +``` + +
+ + + +
+ +### Notes + +- The function writes cumulative sums to the output ndarray and returns no value. +- The input ndarray's length determines the number of elements to process. The caller must provide valid data buffers and an output ndarray containing at least that many elements. +- The function reads the initial sum at the zero-dimensional ndarray's own byte offset before writing output elements. +- If provided an empty input ndarray, the function leaves the output ndarray unchanged. +- The function supports positive, negative, and zero strides. Input and output buffers may overlap; each input element is read before the corresponding output element is written, following the existing strided cumulative-sum implementation's sequential semantics. +- Byte strides and byte offsets must be aligned for double-precision floating-point elements. Element strides, offsets, and all indexed and post-increment positions must be representable using the configured `CBLAS_INT` type. Invalid or unrepresentable ndarray metadata leaves the output ndarray unchanged. +- The implementation reuses the improved Kahan–Babuška algorithm described by Neumaier (1974). + +
+ + + +
+ +### Examples + +```c +#include "stdlib/blas/ext/base/ndarray/dcusumkbn.h" +#include "stdlib/ndarray/ctor.h" +#include "stdlib/ndarray/dtypes.h" +#include "stdlib/ndarray/index_modes.h" +#include "stdlib/ndarray/orders.h" +#include "stdlib/ndarray/base/bytes_per_element.h" +#include +#include +#include + +int main( void ) { + // Create data buffers: + const double dataX[] = { 1.0e16, 1.0, -1.0e16 }; + double dataY[] = { 0.0, 0.0, 0.0 }; + const double dataInitial[] = { 123.0, 0.0 }; + + // Specify the ndarray metadata: + int64_t shape[] = { 3 }; + int64_t strides[] = { STDLIB_NDARRAY_FLOAT64_BYTES_PER_ELEMENT }; + int64_t scalarStrides[] = { 0 }; + int8_t submodes[] = { STDLIB_NDARRAY_INDEX_ERROR }; + const enum STDLIB_NDARRAY_ORDER order = STDLIB_NDARRAY_ROW_MAJOR; + const enum STDLIB_NDARRAY_INDEX_MODE imode = STDLIB_NDARRAY_INDEX_ERROR; + + // Create one-dimensional input and output ndarrays: + struct ndarray *x = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT64, (uint8_t *)dataX, 1, shape, strides, 0, order, imode, 1, submodes ); + struct ndarray *y = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT64, (uint8_t *)dataY, 1, shape, strides, 0, order, imode, 1, submodes ); + + // Select an initial sum of zero at the scalar's own byte offset: + struct ndarray *initial = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT64, (uint8_t *)dataInitial, 0, NULL, scalarStrides, STDLIB_NDARRAY_FLOAT64_BYTES_PER_ELEMENT, order, imode, 1, submodes ); + int status = EXIT_SUCCESS; + if ( x == NULL || y == NULL || initial == NULL ) { + fprintf( stderr, "Error allocating ndarray descriptors.\n" ); + status = EXIT_FAILURE; + } else { + const struct ndarray *arrays[] = { x, y, initial }; + stdlib_blas_ext_dcusumkbn( arrays ); + + // Compensated summation retains the unit term after cancellation: + if ( dataY[ 0 ] != 1.0e16 || dataY[ 1 ] != 1.0e16 || dataY[ 2 ] != 1.0 ) { + fprintf( stderr, "Unexpected cumulative sum.\n" ); + status = EXIT_FAILURE; + } + for ( int i = 0; i < 3; i++ ) { + printf( "y[ %i ] = %.17g\n", i, dataY[ i ] ); + } + } + + // Free any successfully allocated descriptors: + if ( x != NULL ) { + stdlib_ndarray_free( x ); + } + if ( y != NULL ) { + stdlib_ndarray_free( y ); + } + if ( initial != NULL ) { + stdlib_ndarray_free( initial ); + } + return status; +} +``` + +
+ + + +
+ + +