stdlib-js / google-summer-of-code

Google Summer of Code resources.
https://github.com/stdlib-js/stdlib
23 stars 5 forks source link

[RFC]: add support for boolean arrays in stdlib #65

Closed soumajit23 closed 2 months ago

soumajit23 commented 3 months ago

Full name

Soumajit Chatterjee

University status

Yes

University name

Institute of Engineering and Management, Kolkata

University program

B.Tech in Electronics and Communications Engineering

Expected graduation

2026

Short biography

I am a 2nd year student pursuing a B.Tech in Electronics and Communications Engineering, from Institute of Engineering and Management, Kolkata, where I completed various relevant courses on Statistics, Calculus, Data Structures, and Algorithms. I am highly passionate about software development, especially web development, and have taken courses on Python and web development.

Apart from software, my interest also lies in hardware. I have worked on several Arduino/microcontroller-based projects and other electronics projects.

Timezone

IST (UTC+05:30)

Contact details

email:soumajit12b45@gmail.com, github:soumajit23, IRC nick:soumajit23

Platform

Windows

Editor

I use VSCode since it's less cpu draining and the extensive extension options provide the ability to customize the editor according to requirements. The integrated terminal allows me to run commands and scripts within the editor, increasing productivity.

Programming experience

I have an extensive skill set in various programming languages. I am proficient in HTML, CSS, JavaScript, and C. I also have experience coding in MATLAB, Java, and Python languages.

Furthermore, I am familiar with several technologies such as Bootstrap, Node.js, Express.js, PostgreSQL, EJS, jQuery and REST APIs, and I am well-versed in their usage. I also have a good understanding of CLI usage.

Some projects I have worked on:

JavaScript experience

I am proficient in JavaScript, having built projects, which use JavaScript for both frontend and backend development.

A thing I like about JavaScript is its vast ecosystem of libraries and frameworks, that simplify development for various tasks like user interface creation, data manipulation, and more. Also, JavaScript has a large and active community of developers who contribute to its growth and improvement. This means there are plenty of resources, tutorials, and open-source projects available to help developers like me, learn and solve problems.

Node.js experience

Experience with Node.js for backend development has given me a robust foundation in building efficient server-side applications. Working on projects with Node.js has allowed me to harness its extensive ecosystem of libraries and frameworks, enabling rapid development and deployment of features. I have implemented RESTful APIs, used frameworks such as Express.js to build efficient server applications, and built projects that have the usage of Node.js.

C/Fortran experience

My familiarity with the C language, gained through university coursework spanning the second and third semesters, has given me a solid understanding of fundamental programming concepts and principles. I've explored various data structures like arrays, linked lists, stacks, queues, trees, and graphs, understanding their implementations, operations, and applications.

Interest in stdlib

Everything, from the source code to the pull requests is well organized, properly named, and easy to follow and refer to. This makes contributing to stdlib much easier and more convenient. The community is also very welcoming to people like me who are new to open-source contributions.

Furthermore, since I am passionate about mathematics and always get intrigued to learn new ways to implement mathematical and scientific computations to coding, stdlib seems like the perfect place to do so.

Version control

Yes

Contributions to stdlib

I have 3 open PRs as of now:

Goals

The primary goal of this project is to enhance stdlib for JavaScript by introducing support for boolean arrays (BooleanArray). Currently, stdlib provides extensive support for numeric arrays but lacks dedicated support for boolean data types. The introduction of BooleanArray aims to address this and provide support for boolean values. This project will refer to previously added custom-typed arrays, namely Complex64Array and Complex128Array.

@stdlib/array/bool Package Creation:

The key objective is to create a new @stdlib/array/bool package that exposes a BooleanArray constructor, enabling developers to create and manipulate boolean arrays efficiently. This involves implementing standard array methods, such as indexing, iteration, and manipulation while adhering to the conventions established by existing typed arrays in stdlib.

For example,

 // Create a boolean array from a Uint8Array:
 var arr = new Uint8Array([1, 0, 1, 1, 0]);
 var boolArray = new BooleanArray(arr);

 console.log(boolArray); // => [true, false, true, true, false]
'use strict';

// MODULES
var bench = require('@stdlib/bench');
var ArrayBuffer = require('@stdlib/array/buffer');
var Uint8Array = require('@stdlib/array/uint8');
var isArrayBuffer = require('@stdlib/assert/is-arraybuffer');
var isNonNegativeInteger = require('@stdlib/assert/is-nonnegative-integer').isPrimitive;
var ITERATOR_SYMBOL = require('@stdlib/symbol/iterator');
var pkg = require('./../package.json').name;
var BooleanArray = require('./../lib');

// VARIABLES
var opts = {
    'skip': (ITERATOR_SYMBOL === null)
};

// MAIN

// Instantiation Benchmarks

bench(pkg + '::instantiation,new', function benchmark(b) {
    var arr;
    var i;
    b.tic();
    for (i = 0; i < b.iterations; i++) {
        arr = new BooleanArray();
        if (arr.length !== 0) {
            b.fail('should have length 0');
        }
    }
    b.toc();
    if (!(arr instanceof BooleanArray)) {
        b.fail('should return an instance');
    }
    b.pass('benchmark finished');
    b.end();
});

bench(pkg + '::instantiation,no_new', function benchmark(b) {
    var ctor;
    var arr;
    var i;

    ctor = BooleanArray;

    b.tic();
    for (i = 0; i < b.iterations; i++) {
        arr = ctor();
        if (arr.length !== 0) {
            b.fail('should have length 0');
        }
    }
    b.toc();
    if (!(arr instanceof BooleanArray)) {
        b.fail('should return an instance');
    }
    b.pass('benchmark finished');
    b.end();
});

bench(pkg + '::instantiation,length', function benchmark(b) {
    var arr;
    var i;
    b.tic();
    for (i = 0; i < b.iterations; i++) {
        arr = new BooleanArray(0);
        if (arr.length !== 0) {
            b.fail('should have length 0');
        }
    }
    b.toc();
    if (!(arr instanceof BooleanArray)) {
        b.fail('should return an instance');
    }
    b.pass('benchmark finished');
    b.end();
});

bench(pkg + '::instantiation,typed_array', function benchmark(b) {
    var buf;
    var arr;
    var i;

    buf = new Uint8Array(0);

    b.tic();
    for (i = 0; i < b.iterations; i++) {
        arr = new BooleanArray(buf);
        if (arr.length !== 0) {
            b.fail('should have length 0');
        }
    }
    b.toc();
    if (!(arr instanceof BooleanArray)) {
        b.fail('should return an instance');
    }
    b.pass('benchmark finished');
    b.end();
});

bench(pkg + '::instantiation,array', function benchmark(b) {
    var buf;
    var arr;
    var i;

    buf = [];

    b.tic();
    for (i = 0; i < b.iterations; i++) {
        arr = new BooleanArray(buf);
        if (arr.length !== 0) {
            b.fail('should have length 0');
        }
    }
    b.toc();
    if (!(arr instanceof BooleanArray)) {
        b.fail('should return an instance');
    }
    b.pass('benchmark finished');
    b.end();
});

bench(pkg + '::instantiation,iterable', opts, function benchmark(b) {
    var arr;
    var i;

    b.tic();
    for (i = 0; i < b.iterations; i++) {
        arr = new BooleanArray(createIterable());
        if (arr.length !== 0) {
            b.fail('should have length 0');
        }
    }
    b.toc();
    if (!(arr instanceof BooleanArray)) {
        b.fail('should return an instance');
    }
    b.pass('benchmark finished');
    b.end();

    function createIterable() {
        var out = {};
        out[ITERATOR_SYMBOL] = iterator;
        return out;

        function iterator() {
            return {
                'next': next
            };
        }

        function next() {
            return {
                'done': true
            };
        }
    }
});

bench(pkg + '::instantiation,arraybuffer', function benchmark(b) {
    var buf;
    var arr;
    var i;

    buf = new ArrayBuffer(0);

    b.tic();
    for (i = 0; i < b.iterations; i++) {
        arr = new BooleanArray(buf);
        if (arr.length !== 0) {
            b.fail('should have length 0');
        }
    }
    b.toc();
    if (!(arr instanceof BooleanArray)) {
        b.fail('should return an instance');
    }
    b.pass('benchmark finished');
    b.end();
});

bench(pkg + '::instantiation,arraybuffer,byte_offset', function benchmark(b) {
    var buf;
    var arr;
    var i;

    buf = new ArrayBuffer(8);

    b.tic();
    for (i = 0; i < b.iterations; i++) {
        arr = new BooleanArray(buf, 8);
        if (arr.length !== 0) {
            b.fail('should have length 0');
        }
    }
    b.toc();
    if (!(arr instanceof BooleanArray)) {
        b.fail('should return an instance');
    }
    b.pass('benchmark finished');
    b.end();
});

bench(pkg + '::instantiation,arraybuffer,byte_offset,length', function benchmark(b) {
    var buf;
    var arr;
    var i;

    buf = new ArrayBuffer(8);

    b.tic();
    for (i = 0; i < b.iterations; i++) {
        arr = new BooleanArray(buf, 8, 0);
        if (arr.length !== 0) {
            b.fail('should have length 0');
        }
    }
    b.toc();
    if (!(arr instanceof BooleanArray)) {
        b.fail('should return an instance');
    }
    b.pass('benchmark finished');
    b.end();
});

bench(pkg + '::get:buffer', function benchmark(b) {
    var arr;
    var v;
    var i;

    arr = new BooleanArray();

    b.tic();
    for (i = 0; i < b.iterations; i++) {
        v = arr.buffer;
        if (typeof v !== 'object') {
            b.fail('should return an object');
        }
    }
    b.toc();
    if (!isArrayBuffer(v)) {
        b.fail('should return an ArrayBuffer');
    }
    b.pass('benchmark finished');
    b.end();
});

bench(pkg + '::get:byteLength', function benchmark(b) {
    var arr;
    var v;
    var i;

    arr = new BooleanArray();

    b.tic();
    for (i = 0; i < b.iterations; i++) {
        v = arr.byteLength;
        if (v !== v) {
            b.fail('should not return NaN');
        }
    }
    b.toc();
    if (!isNonNegativeInteger(v)) {
        b.fail('should return a nonnegative integer');
    }
    b.pass('benchmark finished');
    b.end();
});

bench(pkg + '::get:byteOffset', function benchmark(b) {
    var arr;
    var v;
    var i;

    arr = new BooleanArray();

    b.tic();
    for (i = 0; i < b.iterations; i++) {
        v = arr.byteOffset;
        if (v !== v) {
            b.fail('should not return NaN');
        }
    }
    b.toc();
    if (!isNonNegativeInteger(v)) {
        b.fail('should return a nonnegative integer');
    }
    b.pass('benchmark finished');
    b.end();
});

bench(pkg + '::get:length', function benchmark(b) {
    var arr;
    var v;
    var i;

    arr = new BooleanArray();

    b.tic();
    for (i = 0; i < b.iterations; i++) {
        v = arr.length;
        if (v !== v) {
            b.fail('should not return NaN');
        }
    }
    b.toc();
    if (!isNonNegativeInteger(v)) {
        b.fail('should return a nonnegative integer');
    }
    b.pass('benchmark finished');
    b.end();
});

Other files like benchmark.fill.js, benchmark.filter.js, benchmark.map.js, benchmark.to_string.js, etc. will be added to run benchmarks for a vast set of operations.

'use strict';

// MODULES
var Uint8Array = require('@stdlib/array/uint8');
var logEach = require('@stdlib/console/log-each');
var BooleanArray = require('./../lib');

// Create a boolean array from a Uint8Array buffer view:
var arr = new Uint8Array([1, 0, 1, 1, 0, 0]);
var boolArray = new BooleanArray(arr.buffer, 0, 6);

// Log each boolean value:
logEach('%s', boolArray);
'use strict';

// MAIN //

/**
* Returns a strided array of boolean values.
*
* @private
* @param {Uint8Array} buf - output array
* @param {Array} arr - array containing boolean values
* @returns {(Uint8Array|null)} output array or null
*/
function fromArray( buf, arr ) {
    var len = arr.length;
    for (var i = 0; i < len; i++) {
        if (typeof arr[i] !== 'boolean') {
            return null;
        }
        buf[i] = arr[i] ? 1 : 0;
    }
    return buf;
}

// EXPORTS //

module.exports = fromArray;

This file exports a fromArray function to provide functionality to convert an array of boolean values into a strided array. Similarly other files like from_iterator.js, main.js will be added.

Tests, benchmarks and examples will be run thoroughly to address any issue or bug in the code. To run tests,

$ make TESTS_FILTER=".*/array/bool/.*" test

will be run. Similarly, for benchmarks and examples,

$ make BENCHMARKS_FILTER=".*/array/bool/.*" benchmark
$ make EXAMPLES_FILTER=".*/array/bool/.*" examples

will be run.

Integration of BooleanArray Throughout stdlib:

The project aims to integrate BooleanArray seamlessly throughout stdlib, ensuring compatibility with existing modules and functions wherever arrays are utilized. This integration effort includes updating documentation, writing tests, refining the implementation based on feedback, etc. This work will probably make up the majority of this project and will require most of the time invested in making sure of proper integration throughout stdlib.

var indexOf = require( '@stdlib/utils/index-of' );
var dtypes = require( '@stdlib/array/dtypes' );

var DTYPES = dtypes();

function isdtype( str ) {
    if ( indexOf( DTYPES, str ) === -1 ) {
        return false;
    }
    return true;
}

var bool = isdtype( 'bool' );
//returns true

Here, bool should return true after integration of boolean array in the namespace.

var dtypes = require( '@stdlib/array/typed-real-dtypes' );
var filledarray = require( '@stdlib/array/filled' );

var arr = filledarray( 1, 3, 'bool' );
// returns <BooleanArray>[ true, true, true ]

These are some of the integration work of boolean array in @stdlib/array/*. Further work will be done to add support of boolean arrays. Namespaces like @stdlib/array/to-fancy, @stdlib/array/typed, etc. will be worked upon and updated accordingly.

var indexOf = require( '@stdlib/utils/index-of' );
var dtypes = require( '@stdlib/strided/dtypes' );

var DTYPES = dtypes();
var bool;

function isdtype( str ) {
    return ( indexOf( DTYPES, str ) >= 0 );
}

bool = isdtype( 'bool' );
// returns true

@stdlib/strided/dtypes will be updated to support boolean array data type.

var BooleanArray = require( '@stdlib/array/bool' );
var Float32Array = require( '@stdlib/array/float32' );
var isBooleanArray = require( '@stdlib/assert/is-booleanarray' );

var bool = isBooleanArray( new BooleanArray( 10 ) );
// returns true

bool = isBooleanArray( new Float32Array( 10 ) );
// returns false

isBooleanArray tests if a value is a BooleanArray.

Support for Boolean Arrays in ndarray and strided array APIs

The project will also support BooleanArray instances as backing for ndarrays and strided arrays. This entails working with C APIs and potentially modifying existing ndarrays and strided arrays functionality to accommodate boolean arrays effectively.

#include "stdlib/strided/base/binary/pp_p.h"
#include "stdlib/strided/base/binary/macros.h"
#include <stdint.h>

/**
* Applies a binary callback to strided input array elements and assigns results to elements in a strided output array.
*
* @param arrays   array whose first two elements are pointers to strided input arrays and whose last element is a pointer to a strided output array
* @param shape    array whose only element is the number of elements over which to iterate
* @param strides  array containing strides (in bytes) for each strided array
* @param fcn      callback
*
* @example
* #include "stdlib/strided/base/binary/pp_p.h"
* #include <stdint.h>
*
* // Create underlying byte arrays:
* uint8_t x[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
* uint8_t y[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
* uint8_t out[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
*
* // Define a pointer to an array containing pointers to strided arrays:
* uint8_t *arrays[] = { x, y, out };
*
* // Define the strides:
* int64_t strides[] = { 1, 1, 1 };
*
* // Define the number of elements over which to iterate:
* int64_t shape[] = { 3 };
*
* // Define a callback:
* static bool add_bool( bool x, bool y ) {
*     return x + y; // Addition operation on boolean values
* }
*
* // Apply the callback:
* stdlib_strided_pp_p( arrays, shape, strides, (void *)add_bool );
*/
void stdlib_strided_pp_p( uint8_t *arrays[], const int64_t *shape, const int64_t *strides, void *fcn ) {
    typedef bool func_type( const bool x, const bool y );
    func_type *f = (func_type *)fcn;
    STDLIB_STRIDED_BINARY_LOOP_CLBK( bool, bool, bool )
}

Function void stdlib_strided_pp_p(...), can be implemented in the @stdlib/strided/base/binary namespace. The function takes two boolean array inputs, their shapes and strides, a callback function, and performs element-wise binary operations on the input arrays, storing the results in the boolean array output.

#ifndef STDLIB_STRIDED_BASE_BINARY_P_AS_K_H
#define STDLIB_STRIDED_BASE_BINARY_P_AS_K_H

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
* Applies a nullary callback to strided input array elements and assigns results to elements in a strided output array.
*/
void stdlib_strided_p_as_k( uint8_t *arrays[], const int64_t *shape, const int64_t *strides, void *fcn );

#ifdef __cplusplus
}
#endif

#endif // !STDLIB_STRIDED_BASE_BINARY_P_AS_K_H

Implemented in @stdlib/strided/base/nullary. To apply the nullary callback,

#include <stdint.h>

// Create underlying byte arrays:
uint8_t out[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

// Define a pointer to an array containing pointers to strided arrays:
uint8_t *arrays[] = { out };

// Define the strides:
int64_t strides[] = { 8 };

// Define the number of elements over which to iterate:
int64_t shape[] = { 3 };

// Define a callback:
static int16_t fcn( void ) {
    return 3;
}

// Apply the callback:
stdlib_strided_p_as_k( arrays, shape, strides, (void *)fcn );

These are some of the APIs to be implemented for strided arrays. Further careful addition of APIs would be done.

#ifndef STDLIB_NDARRAY_BASE_UNARY_P_P_AS_K_K_H
#define STDLIB_NDARRAY_BASE_UNARY_P_P_AS_K_K_H

#include "stdlib/ndarray/ctor.h"
#include <stdint.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

/**
* Applies a unary callback to an input ndarray and assigns results to elements in an output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a zero-dimensional input ndarray and assigns results to elements in a zero-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_0d( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a one-dimensional input ndarray and assigns results to elements in a one-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_1d( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a two-dimensional input ndarray and assigns results to elements in a two-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_2d( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a two-dimensional input ndarray and assigns results to elements in a two-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_2d_blocked( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a three-dimensional input ndarray and assigns results to elements in a three-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_3d( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a three-dimensional input ndarray and assigns results to elements in a three-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_3d_blocked( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a four-dimensional input ndarray and assigns results to elements in a four-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_4d( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a four-dimensional input ndarray and assigns results to elements in a four-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_4d_blocked( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a five-dimensional input ndarray and assigns results to elements in a five-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_5d( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a five-dimensional input ndarray and assigns results to elements in a five-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_5d_blocked( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a six-dimensional input ndarray and assigns results to elements in a six-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_6d( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a six-dimensional input ndarray and assigns results to elements in a six-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_6d_blocked( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a seven-dimensional input ndarray and assigns results to elements in a seven-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_7d( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a seven-dimensional input ndarray and assigns results to elements in a seven-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_7d_blocked( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to an eight-dimensional input ndarray and assigns results to elements in an eight-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_8d( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to an eight-dimensional input ndarray and assigns results to elements in an eight-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_8d_blocked( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a nine-dimensional input ndarray and assigns results to elements in a nine-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_9d( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a nine-dimensional input ndarray and assigns results to elements in a nine-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_9d_blocked( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a ten-dimensional input ndarray and assigns results to elements in a ten-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_10d( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to a ten-dimensional input ndarray and assigns results to elements in a ten-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_10d_blocked( struct ndarray *arrays[], void *fcn );

/**
* Applies a unary callback to an n-dimensional input ndarray and assigns results to elements in an n-dimensional output ndarray.
*/
int8_t stdlib_ndarray_p_p_as_k_k_nd( struct ndarray *arrays[], void *fcn );

#ifdef __cplusplus
}
#endif

#endif // !STDLIB_NDARRAY_BASE_UNARY_P_P_AS_K_K_H

Implemented in @stdlib/ndarray/base/unary. To apply callback,

#include "stdlib/ndarray/dtypes.h"
#include "stdlib/ndarray/index_modes.h"
#include "stdlib/ndarray/orders.h"
#include "stdlib/ndarray/ctor.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

// Define the ndarray data types:
enum STDLIB_NDARRAY_DTYPE xdtype = STDLIB_NDARRAY_UINT8;
enum STDLIB_NDARRAY_DTYPE ydtype = STDLIB_NDARRAY_INT16;

// Create underlying byte arrays:
uint8_t xbuf[] = { 0, 0, 0, 0 };
uint8_t ybuf[] = { 0, 0, 0, 0, 0, 0, 0, 0 };

// Define the number of dimensions:
int64_t ndims = 2;

// Define the array shapes:
int64_t shape[] = { 2, 2 };

// Define the strides:
int64_t sx[] = { 2, 1 };
int64_t sy[] = { 4, 2 };

// Define the offsets:
int64_t ox = 0;
int64_t oy = 0;

// Define the array order:
enum STDLIB_NDARRAY_ORDER order = STDLIB_NDARRAY_ROW_MAJOR;

// Specify the index mode:
enum STDLIB_NDARRAY_INDEX_MODE imode = STDLIB_NDARRAY_INDEX_ERROR;

// Specify the subscript index modes:
int8_t submodes[] = { imode };
int64_t nsubmodes = 1;

// Create an input ndarray:
struct ndarray *x = stdlib_ndarray_allocate( xdtype, xbuf, ndims, shape, sx, ox, order, imode, nsubmodes, submodes );
if ( x == NULL ) {
    fprintf( stderr, "Error allocating memory.\n" );
    exit( EXIT_FAILURE );
}

// Create an output ndarray:
struct ndarray *y = stdlib_ndarray_allocate( ydtype, ybuf, ndims, shape, sy, oy, order, imode, nsubmodes, submodes );
if ( y == NULL ) {
    fprintf( stderr, "Error allocating memory.\n" );
    exit( EXIT_FAILURE );
}

// Create an array containing the ndarrays:
struct ndarray *arrays[] = { x, y };

// Define a callback:
static int16_t fcn( const int16_t x ) {
    return x;
}

// Apply the callback:
int8_t status = stdlib_ndarray_p_p_as_k_k( arrays, (void *)fcn );
if ( status != 0 ) {
    fprintf( stderr, "Error during computation.\n" );
    exit( EXIT_FAILURE );
}

// ...

// Free allocated memory:
stdlib_ndarray_free( x );
stdlib_ndarray_free( y );

Further careful addition and implementation of APIs will be done for ndarrays to support boolean arrays.

Throughout development, attention will be paid to performance optimizations, ensuring that BooleanArray operations are efficient and scalable. Moreover, comprehensive documentation will guide developers in utilizing BooleanArray effectively within their projects.

This project aims to enrich the stdlib ecosystem with a dedicated boolean array data type, empowering JavaScript developers with enhanced data manipulation and analysis capabilities, particularly in scenarios requiring boolean-based indexing and filtering operations.

Why this project?

The addition of BooleanArray support expands the capabilities of stdlib by providing developers with a dedicated data type for boolean arrays. This enhances its versatility, allowing for more efficient and expressive manipulation of boolean data within JavaScript applications. By addressing the need for boolean arrays within stdlib, the project demonstrates responsiveness to the needs of the community. Providing features that align with developers' requirements enhances satisfaction and fosters continued adoption and support for stdlib.

I would like to mention that contributing to this project would not only help in achieving the project's goals but also aid in my personal and professional growth. It would provide me with an opportunity to work on a complex project, collaborate with others, and contribute positively to the community. Moreover, this project would enable me to enhance my JavaScript programming skills, especially in the areas of array manipulation and API design.

Qualifications

Working on this project requires knowledge of JavaScript, C, Node,js, and Native Addons. Whether through University coursework or by building projects, I feel like I have the necessary knowledge of these technologies and would be able to implement these in a major project.

I have also gone through the source code and realized the needs of stdlib and the necessity of this project.

Prior art

Implementation of custom-typed arrays similar to the proposed BooleanArray in other programming languages and libraries:

Studying these implementations could prove helpful when working on @stdlib/array/bool.

Additionally, since there exists prior art for adding custom-typed arrays to stdlib; namely, Complex64Array and Complex128Array, these should serve as the appropriate approach to work on @stdlib/array/bool.

Commitment

I do not have any other professional commitment for the entire summer, and my academic schedule does not clash with the coding period. Therefore, I plan on dedicating 30 hours per week to this project for the entire 12-week program duration.

Schedule

Assuming a 12 week schedule,

Community Bonding Period:

Week 1-2: BooleanArray Implementation

Week 3-5: Integration with stdlib Modules

Week 6-7: Support for ndarrays (midterm)

Week 8: Optimizations to improve the integration with ndarrays

Week 9-10: Documentation and Testing

Week 11-12: Refinement and Finalization

Final Week: Submission

Note:

Integration of BooleanArray throughout stdlib and adding support for boolean arrays in ndarrays could be challenging and might take longer than mentioned in the schedule. This might become evident when working on the project and the schedule could be updated accordingly.

Related issues

43

Checklist

Planeshifter commented 3 months ago

You show a good understanding of the required technologies and have provided examples of previous projects. However, keep in mind the proverb "show, don't tell": When mentioning prior projects from your portfolio, it's always more effective if you can also link to them.

Your proposal itself is comprehensive, but it would be good to include more details on what APIs would have to be implemented and the potential challenges you may run into and how they might be addressed.

kgryte commented 3 months ago

@soumajit23 Thank you for sharing a draft of your proposal. Building on Philipp's comments, I have a few of my own:

soumajit23 commented 3 months ago

@kgryte Thank you for reviewing the proposal! I have made the changes you suggested. Is there anything else you would like me to implement?