Outer sum/sub/div
It would be nice to have optimized expressions for outer add/sub/div, e.g.:
Vector<3, columnVector> a;
Vector<3, rowVector> b;
Matrix<double,3,3> m = a + b;
// [ a0+b0, a0+b1, a0+b2 ]
// [ a1+b0, a1+b1, a1+b2 ]
// [ a2+b0, a2+b1, a2+b2 ]
It would not interfere with existing code since these operations require already to have the same transpose flag to work component-wise.
Comments (5)
-
-
reporter Hi Klaus,
It is indeed not a common operation. However, they are available in e.g. numpy, mathematica. I do not have explicit application, some people could make use of it in nbody simulation or deep learning. I mainly asked about it because it seemed a consistent and concise approach within blaze to fill this gap.
In fact what confuses me is why there is an error when one tries to add/sub/div two vectors with different transpose flag. Outer add/sub/div seemed to be consistent with blaze behavior, hence my question. Alternatively you can argue that blaze should follow strict mathematics, but then the only available add operation between vectors is the component-wise way. Therefore, disabling this combination generates friction for the user in both cases. Is there another view of this problem ?
Regarding the outer add/sub/div operations, as you mentioned it could be done with the binary
map
function if it is extended to two vectors with different transpose flags, and return a correctly sized matrix. That would resolve add/sub/div at once by leaving the user customize the applied function.Cheers, Fabien
-
-
assigned issue to
-
assigned issue to
-
- changed status to open
-
- changed status to resolved
Summary
The feature has been implemented, tested, optimized, and documented as required. It is immediately available via cloning the Blaze repository and will be officially released in Blaze 3.7.
Outer map() Operation
Via the
map()
functions it is possible to execute componentwise custom operations on vectors. Applying themap()
function to a column vector and a row vector results in the outer map of the two vectors. The following example demonstrates the outer sum of a column vector and a row vector:blaze::DynamicVector<int,columnVector> v1{ 2, 5, -1 }; blaze::DynamicVector<int,rowVector> v2{ -1, 3, -2, 4 }; // Results in the matrix // // ( 1 5 0 6 ) // A = ( 4 8 3 9 ) // ( -2 2 -3 3 ) // blaze::StaticMatrix<int,3UL,4UL> M1 = map( v1, v2, []( int a, int b ){ return a + b; } );
Outer Sum
The addition between a column vector and a row vector results in the outer sum of the two vectors:
blaze::StaticVector<int,3UL,columnVector> v1{ 2, 5, -1 }; blaze::DynamicVector<int,rowVector> v2{ -1, 3, -2, 4 }; // Results in the matrix // // ( 1 5 0 6 ) // A = ( 4 8 3 9 ) // ( -2 2 -3 3 ) // blaze::StaticMatrix<int,3UL,4UL> M1 = v1 + v2;
The
trans()
function can be used to transpose a vector as necessary:blaze::StaticVector<int,2UL,rowVector> v1{ 2, 5, -1 }; blaze::DynamicVector<int,rowVector> v2{ -1, 3, -2, 4 }; blaze::StaticMatrix<int,3UL,4UL> M1 = trans( v1 ) + v2;
Outer Difference
The subtraction between a column vector and a row vector results in the outer difference of the two vectors:
blaze::StaticVector<int,3UL,columnVector> v1{ 2, 5, -1 }; blaze::DynamicVector<int,rowVector> v2{ -1, 3, -2, 4 }; // Results in the matrix // // ( 3 -1 4 -2 ) // A = ( 6 2 7 1 ) // ( 0 -4 1 -5 ) // blaze::StaticMatrix<int,3UL,4UL> M1 = v1 - v2;
The
trans()
function can be used to transpose a vector as necessary:blaze::StaticVector<int,2UL,rowVector> v1{ 2, 5, -1 }; blaze::DynamicVector<int,rowVector> v2{ -1, 3, -2, 4 }; blaze::StaticMatrix<int,3UL,4UL> M1 = trans( v1 ) - v2;
Outer Quotient
The division between a column vector and a row vector results in the outer quotient of the two vectors:
blaze::StaticVector<double,3UL,columnVector> v1{ 2, 5, -1 }; blaze::DynamicVector<double,rowVector> v2{ -1, 5, -2, 4 }; // Results in the matrix // // ( -2 0.4 -1 0.5 ) // A = ( -5 1 -2.5 1.25 ) // ( 1 -0.2 0.5 -0.25 ) // blaze::StaticMatrix<int,3UL,4UL> M1 = v1 / v2;
The
trans()
function can be used to transpose a vector as necessary:blaze::StaticVector<int,2UL,rowVector> v1{ 2, 5, -1 }; blaze::DynamicVector<int,rowVector> v2{ -1, 5, -2, 4 }; blaze::StaticMatrix<int,3UL,4UL> M1 = trans( v1 ) / v2;
Note that all values of the divisor must be non-zero and that no checks are performed to assert this precondition!
- Log in to comment
Hi Fabien!
Thanks a lot for creating this proposal. We have already taken some time to think about it. So far we have never encountered an outer addition, subtraction or division and therefore never considered it. We suspect that this would cause more confusion and questions than it would help. Could you please give us some additional information, especially for which kind of application you need these operations? Is there any way to generalize this operation to enable you to customize it for your application (e.g. via an according
map()
function)?Best regards,
Klaus!