This is a follow-up question for An element_wise_add Function For Boost.MultiArray in C++ and An Add/Minus Operator For Boost.MultiArray in C++. Besides the basic element-wise add / minus operations, I am trying to implement an element_wise_multiplication
function and an element_wise_division
function here for Boost.MultiArray. The new concept is_multiplicable
and is_divisible
used here are as below.
template<typename T>
concept is_multiplicable = requires(T x)
{
x * x;
};
template<typename T>
concept is_divisible = requires(T x)
{
x / x;
};
The another used concept is_multi_array
:
template<typename T>
concept is_multi_array = requires(T x)
{
x.num_dimensions();
x.shape();
boost::multi_array(x);
};
The implementation of element_wise_multiplication
function and element_wise_division
function:
// Multiplication
template<class T1, class T2> requires (is_multiplicable<T1> && is_multiplicable<T2>)
auto element_wise_multiplication(const T1& input1, const T2& input2)
{
return input1 * input2;
}
template<class T1, class T2> requires (is_multi_array<T1> && is_multi_array<T2>)
auto element_wise_multiplication(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); // 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] = element_wise_multiplication(input1[i], input2[i]);
}
return output;
}
// Division
template<class T1, class T2> requires (is_divisible<T1> && is_divisible<T2>)
auto element_wise_division(const T1& input1, const T2& input2)
{
if (input2 == 0)
{
throw std::logic_error("Divide by zero exception"); // Handle the case of dividing by zero exception
}
return input1 / input2;
}
template<class T1, class T2> requires (is_multi_array<T1> && is_multi_array<T2>)
auto element_wise_division(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); // 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] = element_wise_division(input1[i], input2[i]);
}
return output;
}
The test for the element_wise_multiplication
function and the element_wise_division
function:
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 = 1;
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 test_result = A;
for (size_t i = 0; i < 3; i++)
{
test_result = element_wise_multiplication(test_result, A);
}
test_result = element_wise_division(test_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 << test_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++ and An Add/Minus Operator For Boost.MultiArray in C++
What changes has been made in the code since last question?
The previous questions are the implementation of add / minus operations for Boost.MultiArray and I am trying to implement an
element_wise_multiplication
function andelement_wise_division
function here.Why a new review is being asked for?
There are two new concepts
is_multiplicable
andis_divisible
have been added here. I am not sure is this a good idea although it seems to work fine with the test example mentioned above. On the other hand, the reason for not overloading the operator* and operator/ directly is that the symbol*
and/
are hard to indicate element-wise multiplication and division clearly. There are some more complex high dimensional matrix multiplication calculations maybe like this one. If there is any further suggestion about this idea, please let me know.