Search code examples
arrayfire

Multiplying a vector component with an array in ArrayFire


I'm getting an error while trying to multiply a vector component with an array (element-wise multiplication or broadcast). The docs show that this overloaded case for * should be fine:

AFAPI array operator* (const float &lhs, const array &rhs)
Multiplies two arrays or an array and a value. (const array&, const array&)

But according to the error message below, perhaps vect(0) needs to be further flattened or reduced so that the sizes are consistent?

The error statement is clear:

Invalid dimension for argument 1 Expected: ldims == rides


Below is the code:

#include <arrayfire.h>

int main(int argc, char *argv[])
{
    int device = argc > 1 ? atoi(argv[1]) : 0;
    af::setDevice(device);
    af::info();

    int n = 3;
    int N = 5;

    // Create the arrays:
    af::array matrix = af::constant(0,n,n,f32); // 3 x 3 float array of zeros
    af::array vect = af::seq(1,N); // A col vector of floats: {1.0, ... ,5.0}

    // Show the arrays:
    af_print(matrix);
    af_print(vect);

    // Print a single component of the vector:
    af_print(vect(0));

    // This line produces the error (see below):
    af_print(vect(0) * matrix); // Why doesn't this work?

    // But somthing like this is fine:
    af_print(1.0 * matrix);

    return 0;
}

Producing the output:

ArrayFire v3.3.2
ATI Radeon HD 6750M

matrix
[3 3 1 1]
0.0000 0.0000 0.0000
0.0000 0.0000 0.0000
0.0000 0.0000 0.0000

vect
[5 1 1 1]
1.0000
2.0000
3.0000
4.0000
5.0000

vect(0)
[1 1 1 1]
1.0000

The dims() output of af_print() for the matrix = [3 3 1 1], and vect(0) = [1 1 1 1], make me suspicious, but I'm not sure how to flatten further. One would think this example to be a common way of using the ArrayFire API.

The error exception that is thrown is:

libc++abi.dylib: terminating with uncaught exception of type af::exception: ArrayFire Exception (Invalid input size:203): In function getOutDims In file src/backend/ArrayInfo.cpp:173
Invalid dimension for argument 1 Expected: ldims == rides
In function af::array af::operator*(const af::array &, const af::array &)


Adding a use-case to clarify: In practice I am constructing a final array by summation of coeff(k) * (a 2-d slice of a 3-d array Z):

for (int j = 0; j<indx.dims(0); ++j)
  final += coeff(indx(j)) * Z(af::span,af::span,indx(j));

I'll look into using a gfor but initially just wanted to get the correct numerical output. Note also that the vector: index is predefined, e.g., say index = {1, 2, 4, 7, ...} and the elements are not necessarily in sequence; this allows the selection of specific terms.


Solution

  • Since OP added a usecase since the last answer, this is how you write a fully vectorized version in arrayfire.

    array coeffs = moddims(coeff(indx), 1, 1, coeff.elements());
    array final = sum(Z(span, span, indx) * tile(coeffs, Z.dims(0), Z.dims(1)), 2);