From 4d2cb65b4733d0aa95cb443fd11ceb305573f851 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Fri, 2 Oct 2026 13:40:09 +0200 Subject: [PATCH] feat: add C implementation for blas/ext/base/ndarray/dwhere Add bytewise conditional selection, the Node-API bridge and native dispatch while preserving BooleanArray semantics, independent ndarray views, sequential aliases and legacy JavaScript fallback behavior. Add meaningful native parity, regression coverage and complete C package assets. Assisted-by: OpenAI Codex --- .../blas/ext/base/ndarray/dwhere/README.md | 132 ++++++ .../dwhere/benchmark/benchmark.native.js | 121 +++++ .../base/ndarray/dwhere/benchmark/c/Makefile | 146 ++++++ .../dwhere/benchmark/c/benchmark.length.c | 229 +++++++++ .../blas/ext/base/ndarray/dwhere/binding.gyp | 170 +++++++ .../base/ndarray/dwhere/examples/c/Makefile | 146 ++++++ .../base/ndarray/dwhere/examples/c/example.c | 68 +++ .../blas/ext/base/ndarray/dwhere/include.gypi | 53 +++ .../stdlib/blas/ext/base/ndarray/dwhere.h | 40 ++ .../base/ndarray/dwhere/lib/can_use_native.js | 93 ++++ .../blas/ext/base/ndarray/dwhere/lib/index.js | 16 +- .../ext/base/ndarray/dwhere/lib/native.js | 98 ++++ .../ext/base/ndarray/dwhere/manifest.json | 101 ++++ .../blas/ext/base/ndarray/dwhere/package.json | 4 + .../blas/ext/base/ndarray/dwhere/src/Makefile | 70 +++ .../blas/ext/base/ndarray/dwhere/src/addon.c | 64 +++ .../blas/ext/base/ndarray/dwhere/src/main.c | 65 +++ .../base/ndarray/dwhere/test/test.dispatch.js | 77 ++++ .../ext/base/ndarray/dwhere/test/test.main.js | 412 +++++++++++++++++ .../base/ndarray/dwhere/test/test.native.js | 421 +++++++++++++++++ .../ndarray/dwhere/test/test.native.parity.js | 433 ++++++++++++++++++ 21 files changed, 2958 insertions(+), 1 deletion(-) create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/benchmark/benchmark.native.js create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/benchmark/c/Makefile create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/benchmark/c/benchmark.length.c create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/binding.gyp create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/examples/c/Makefile create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/examples/c/example.c create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/include.gypi create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/include/stdlib/blas/ext/base/ndarray/dwhere.h create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/lib/can_use_native.js create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/lib/native.js create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/manifest.json create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/src/Makefile create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/src/addon.c create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/src/main.c create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/test/test.dispatch.js create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/test/test.main.js create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/test/test.native.js create mode 100644 lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/test/test.native.parity.js diff --git a/lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/README.md b/lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/README.md index 96ed983e7c71..5225a124c0e4 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/README.md +++ b/lib/node_modules/@stdlib/blas/ext/base/ndarray/dwhere/README.md @@ -111,6 +111,138 @@ console.log( ndarray2array( out ) ); + + +* * * + +
+ +## C APIs + +
+ +### Usage + +```c +#include "stdlib/blas/ext/base/ndarray/dwhere.h" +``` + +#### stdlib_blas_ext_dwhere( arrays ) + +Takes elements from one of two one-dimensional double-precision floating-point ndarrays depending on a condition. + +The function accepts the following arguments: + +- **arrays**: `[in] struct ndarray**` list containing the following ndarrays: + + - `[in] struct ndarray*` a one-dimensional boolean condition ndarray. + - `[in] struct ndarray*` first one-dimensional double-precision input ndarray. + - `[in] struct ndarray*` second one-dimensional double-precision input ndarray. + - `[out] struct ndarray*` a one-dimensional double-precision output ndarray. + +```c +void stdlib_blas_ext_dwhere( const struct ndarray *arrays[] ); +``` + +
+ + + +
+ +### Notes + +- The output ndarray is modified in-place. +- A nonzero condition byte selects an element from the first input ndarray; a zero byte selects an element from the second input ndarray. +- Strides and offsets in C ndarray metadata are specified in units of bytes. + +
+ + + +
+ +### Examples + +```c +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 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/blas/ext/base/ndarray/dwhere.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: + uint8_t dataC[] = { 1, 0, 1, 0, 1 }; + double dataX[] = { 1.0, 2.0, 3.0, 4.0, 5.0 }; + double dataY[] = { 6.0, 7.0, 8.0, 9.0, 10.0 }; + double dataOut[] = { 0.0, 0.0, 0.0, 0.0, 0.0 }; + int64_t shape[] = { 5 }; + int64_t strideC[] = { STDLIB_NDARRAY_BOOL_BYTES_PER_ELEMENT }; + int64_t stride[] = { STDLIB_NDARRAY_FLOAT64_BYTES_PER_ELEMENT }; + int8_t submodes[] = { STDLIB_NDARRAY_INDEX_ERROR }; + + // Create ndarrays: + struct ndarray *condition = stdlib_ndarray_allocate( STDLIB_NDARRAY_BOOL, dataC, 1, shape, strideC, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 1, submodes ); + + // cppcheck-suppress invalidPointerCast + struct ndarray *x = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT64, (uint8_t *)dataX, 1, shape, stride, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 1, submodes ); + + // cppcheck-suppress invalidPointerCast + struct ndarray *y = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT64, (uint8_t *)dataY, 1, shape, stride, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 1, submodes ); + + // cppcheck-suppress invalidPointerCast + struct ndarray *out = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT64, (uint8_t *)dataOut, 1, shape, stride, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 1, submodes ); + if ( condition == NULL || x == NULL || y == NULL || out == NULL ) { + fprintf( stderr, "Error allocating memory.\n" ); + stdlib_ndarray_free( condition ); + stdlib_ndarray_free( x ); + stdlib_ndarray_free( y ); + stdlib_ndarray_free( out ); + exit( 1 ); + } + const struct ndarray *arrays[] = { condition, x, y, out }; + stdlib_blas_ext_dwhere( arrays ); + for ( int i = 0; i < 5; i++ ) { + printf( "out[ %i ] = %lf\n", i, dataOut[ i ] ); + } + stdlib_ndarray_free( condition ); + stdlib_ndarray_free( x ); + stdlib_ndarray_free( y ); + stdlib_ndarray_free( out ); +} +``` + +
+ + + +
+ + +