time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

main.c (3157B)


      1 /**
      2 * @license Apache-2.0
      3 *
      4 * Copyright (c) 2021 The Stdlib Authors.
      5 *
      6 * Licensed under the Apache License, Version 2.0 (the "License");
      7 * you may not use this file except in compliance with the License.
      8 * You may obtain a copy of the License at
      9 *
     10 *    http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing, software
     13 * distributed under the License is distributed on an "AS IS" BASIS,
     14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 * See the License for the specific language governing permissions and
     16 * limitations under the License.
     17 */
     18 
     19 #include "stdlib/ndarray/base/broadcast_shapes.h"
     20 #include <stdint.h>
     21 
     22 /**
     23 * Broadcasts array shapes to a single shape.
     24 *
     25 * ## Notes
     26 *
     27 * -   Two respective dimensions in two shape arrays are compatible if
     28 *
     29 *     1.  the dimensions are equal.
     30 *     2.  one dimension is `1`.
     31 *
     32 * -   If successful, the function returns `0`; otherwise, the function returns `-1` (e.g., due to incompatible shapes).
     33 *
     34 * -   Even if the function is unsuccessful, the function may still overwrite elements in the output array before returning. In other words, do not assume that providing incompatible shapes is a no-op with regard to the output array.
     35 *
     36 * @param M        number of array shapes
     37 * @param shapes   pointer to an array containing shape arrays
     38 * @param ndims    array containing the number of dimensions for (i.e., length of) each respective shape array
     39 * @param out      pointer to output array
     40 * @return         status
     41 *
     42 * @example
     43 * #include "stdlib/ndarray/base/broadcast_shapes.h"
     44 * #include <stdint.h>
     45 *
     46 * int64_t N1 = 4;
     47 * int64_t sh1[] = { 8, 1, 6, 1 };
     48 *
     49 * int64_t N2 = 3;
     50 * int64_t sh2[] = { 7, 1, 5 };
     51 *
     52 * int64_t ndims[] = { N1, N2 };
     53 * int64_t *shapes[] = { sh1, sh2 };
     54 *
     55 * int64_t out[] = { 0, 0, 0, 0 };
     56 * int8_t status = stdlib_ndarray_broadcast_shapes( 2, shapes, ndims, out );
     57 */
     58 int8_t stdlib_ndarray_broadcast_shapes( int64_t M, int64_t *shapes[], int64_t ndims[], int64_t *out ) {
     59 	int64_t dim;
     60 	int64_t *sh;
     61 	int64_t n1;
     62 	int64_t n2;
     63 	int64_t d;
     64 	int64_t N;
     65 	int64_t i;
     66 	int64_t j;
     67 
     68 	if ( M == 0 ) {
     69 		return 0;
     70 	}
     71 	sh = shapes[ 0 ];
     72 	N = ndims[ 0 ];
     73 
     74 	// If provided a single input shape array, then the broadcast shape is input shape...
     75 	if ( M == 1 ) {
     76 		for ( i = 0; i < N; i++ ) {
     77 			out[ i ] = sh[ i ];
     78 		}
     79 		return 0;
     80 	}
     81 	// Determine the maximum dimensionality...
     82 	for ( i = 1; i < M; i++ ) {
     83 		if ( ndims[ i ] > N ) {
     84 			N = ndims[ i ];
     85 		}
     86 	}
     87 	// Compute the broadcast shape...
     88 	i = N - 1;
     89 	while ( i >= 0 ) {
     90 		n1 = ndims[ 0 ] - N + i;
     91 		if ( n1 >= 0 ) {
     92 			dim = sh[ n1 ];
     93 		} else {
     94 			dim = 1;
     95 		}
     96 		for ( j = 1; j < M; j++ ) {
     97 			n2 = ndims[ j ] - N + i;
     98 			if ( n2 >= 0 ) {
     99 				d = shapes[ j ][ n2 ];
    100 			} else {
    101 				d = 1;
    102 			}
    103 			if ( dim == 1 ) {
    104 				dim = d;
    105 				continue;
    106 			}
    107 			if ( d == 1 || dim == d ) {
    108 				// When either `d` is `1` or `d` equals the current output shape dimension, the current output shape dimension remains the same...
    109 				continue;
    110 			}
    111 			// The current shape cannot be broadcast against one of the other shapes...
    112 			return -1;
    113 		}
    114 		out[ i ] = dim;
    115 		i -= 1;
    116 	}
    117 	return 0;
    118 }