4
\$\begingroup\$

This is a follow-up question for An element_wise_add Function For Boost.MultiArray in C++. The following code is the improved version based on G. Sliepen's answer. On the other hand, the built-in function .num_dimensions() I used here for the part of array dimension mismatch detection.

template<typename T>
concept is_multi_array = requires(T x)
{
    x.num_dimensions();
    x.shape();
    boost::multi_array(x);
};

//  Add operator
template<class T1, class T2> requires (is_multi_array<T1>&& is_multi_array<T2>)
auto operator+(const T1& input1, const T2& input2)
{
    if (input1.num_dimensions() != input2.num_dimensions())     //  Dimensions are different, unable to perform element-wise add operation
    {
        throw std::logic_error("Array dimensions are different");
    }
    if (*input1.shape() != *input2.shape())                     //  Shapes are different, unable to perform element-wise add operation
    {
        throw std::logic_error("Array shapes are different");
    }
    boost::multi_array output(input1);                          //  [ToDo] drawback to be improved: avoiding copying whole input1 array into output, but with appropriate memory allocation
    for (decltype(+input1.shape()[0]) i = 0; i < input1.shape()[0]; i++)
    {
        output[i] = input1[i] + input2[i];
    }
    return output;
}

//  Minus operator
template<class T1, class T2> requires (is_multi_array<T1>&& is_multi_array<T2>)
auto operator-(const T1& input1, const T2& input2)
{
    if (input1.num_dimensions() != input2.num_dimensions())     //  Dimensions are different, unable to perform element-wise add operation
    {
        throw std::logic_error("Array dimensions are different");
    }
    if (*input1.shape() != *input2.shape())                     //  Shapes are different, unable to perform element-wise add operation
    {
        throw std::logic_error("Array shapes are different");
    }
    boost::multi_array output(input1);                          //  [ToDo] drawback to be improved: avoiding copying whole input1 array into output, but with appropriate memory allocation
    for (decltype(+input1.shape()[0]) i = 0; i < input1.shape()[0]; i++)
    {
        output[i] = input1[i] - input2[i];
    }
    return output;
}

The test of the add/minus operator:

int main()
{
    // Create a 3D array that is 3 x 4 x 2
    typedef boost::multi_array<double, 3> array_type;
    typedef array_type::index index;
    array_type A(boost::extents[3][4][2]);

    // Assign values to the elements
    int values = 0;
    for (index i = 0; i != 3; ++i)
        for (index j = 0; j != 4; ++j)
            for (index k = 0; k != 2; ++k)
                A[i][j][k] = values++;

    for (index i = 0; i != 3; ++i)
        for (index j = 0; j != 4; ++j)
            for (index k = 0; k != 2; ++k)
                std::cout << A[i][j][k] << std::endl;

    auto sum_result = A;
    for (size_t i = 0; i < 3; i++)
    {
        sum_result = sum_result + A;
    }
    sum_result = sum_result - A;
    
    for (index i = 0; i != 3; ++i)
        for (index j = 0; j != 4; ++j)
            for (index k = 0; k != 2; ++k)
                std::cout << sum_result[i][j][k] << std::endl;

    return 0;
}

All suggestions are welcome.

  • Which question it is a follow-up to?

    An element_wise_add Function For Boost.MultiArray in C++

  • What changes has been made in the code since last question?

    The previous question is the implementation of element_wise_add function for Boost.MultiArray. Based on G. Sliepen's suggestion, this kind of element-wise operations could be implemented with C++ operator overloading. As the result, here comes the operator+ and operator- overload functions for Boost.MultiArray.

  • Why a new review is being asked for?

    The operator+ and operator- overload functions here include the exception handling for the situation of different dimensions and shapes. Please check if this usage is appropriate. Moreover, I am still seeking another smarter method to improve the construction of output object. If there is any better idea for deducing the output structure from input without copying process, please let me know.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.