How to effectively multiply 2 TriBandDense?

25 views
Skip to first unread message

Aron Sogor

unread,
Jul 20, 2022, 9:48:43 PM7/20/22
to gonum-dev
Hi,

I have a number of TriBandDense and I would like to multiply, substract them. I can figure out a number of ways to copy to *Dense and than do the operations but was wondering if you have any pointers to do this the most efficient manner.

Aron

Aron Sogor

unread,
Jul 21, 2022, 11:55:00 AM7/21/22
to gonum-dev
I attached my test code (multiply_test.go) and results (*.test).

I am trying to achieve with a and b starting as a TriBandDense, and get C as the MulElem of a+b
c.MulElem(a.T(), b.T())

first I create C as a Dense, and use a.T() and b.T(), the Dense gets the result I expect.
I want to move the Dense to become like a TriBandDense and that is where I struggle:

result := mat.NewTriBandDense(n, k, mat.Upper, /*NEED something else*/ c.RawMatrix().Data)

I attach the source of the test and all the printouts I generate. Any advice would be greatly appreciated.
input_a_multiplied.test
denseResult_multiplied.test
input_a_T_multiplied.test
input_b_T_multiplied.test
result_multiplied.test
input_b_multiplied.test
multiply_test.go

Vladimír Chalupecký

unread,
Aug 11, 2022, 2:00:02 AM8/11/22
to gonum-dev
Hi,

> I can figure out a number of ways to copy to *Dense and than do the operations but was wondering if you have any pointers to do this the most efficient manner.

Using mat.Dense will work but won't be efficient because you'll doing operations on zeroes from the unused triangle and from elements outside of the band.

> first I create C as a Dense, and use a.T() and b.T(), the Dense gets the result I expect.

What you're doing in the test code is not correct and works only by chance thanks to a TriBandDense with n=5,k=4 having the same memory layout as a Dense with m=n=5.

> result := mat.NewTriBandDense(n, k, mat.Upper, /*NEED something else*/ c.RawMatrix().Data)

As you've also apparently realized, you cannot do that, the storage formats are not compatible.

> Any advice would be greatly appreciated.

Since we're currently not providing a MulElem function that takes TriBandDense and returns TriBandDense (it's a rather unusual operation to do with triangular band matrices), you can implement it yourself using At and SetTriBand. You must take care to only set elements within the triangle and band, otherwise you'll get panics. If you wait for the next release, you could simplify that by using the DoNonZero method https://github.com/gonum/gonum/blob/a4dda6a99c494413c752a2fd35338c59448f2207/mat/triband.go#L366

Alternatively, you could implement the operations by working directly with the raw matrix data obtained with RawTriBand. It may be more efficient because you avoid our internal bound checks but also more dangerous because you work with raw data and you avoid our internal bound checks. And you must understand the underlying matrix layout.

Vladimir

Aron Sogor

unread,
Aug 19, 2022, 11:16:52 PM8/19/22
to gonum-dev
Thank you!
Reply all
Reply to author
Forward
0 new messages