Using FFT to compute sumproduct of two 2D arrays - c++

I am doing program to remove noise from image, in it, i need to compute a lot of sums of pointwise multiplications, right now, i do it through direct approach and it takes huge computation cost:
int ret=0, arr1[n][n].arr2[n][n];
for (int i=0;i<n;i++) for (int j=0;j<n;j++) ret+=arr1[i][j]*arr2[i][j];
I was told, that to compute this convolution between two arrays, i should do this (
more details here here ) :
Calculate the DFT of array 1 (via FFT).
Calculate the DFT of array 2 (via FFT).
Multiply the two DFTs element-wise. It should be a complex multiplication.
Calculate the inverse DFT (via FFT) of the multiplied DFTs. That'll be your convolution result.
It seems, that algorithmic part is more or less clear, but i came to a new problem:
I selected fftw for this task, but after a long time, spent by reading it's docs, i still don't see any function for 2D inverse fft which returns not 2D array, but a single value akin to direct approach, not whole 2D array, what am i missing?

Related

Eigen: Modify Rows of Row-Major Sparse Matrix

I am using the Eigen library in C++ for solving sparse linear equations: Ax=b where, A is a square sparse matrix and b is a dense vector with ILU-preconditioned BiCGSTAB. I am initializing the matrix A using the setFromTriplets function. The linear system is generated from discretization of partial differential equations in space and time.
My application changes the matrix slightly at every time-step. I want to modify a small number of rows (around 1% rows) in the matrix in the beginning of each time-step. I am storing the matrix in the row-major format so that I can access the row directly. I don't want to re-assemble the entire matrix from triplets since the number of rows to be modified are around 1%. Moreover, the modification is such that the number of non-zeros in the row are exactly identical. I just want to change the column indices and values. Hence, I do not need to allocate extra memory for the row. After going through the Eigen documentation as well as the forum, I found the functions coeffRef and insert. Both of them will allocate extra memory if the element does not exist. I would like to avoid this since the number of non-zeros are not changing.
Any help is appreciated.

Strategies for filling an Eigen3 sparse matrix when the order of insertion is known

So in my nonlinear finite element solver i use Eigen3 sparse matrices and the LDLT factorization.
The thing is, this factorization needs to be performed many times during a dynamic simulation, and a lot of time is spent inserting the coefficients in the iteration matrix based on triplets (storage is reserved).
Is there any good strategies on how to utilize the fact that the sparsity is unchanged and the order of insertions are the same? When forming this matrix, looping over the elements, coupligs etc. in the model, the order of insertion are the same at every time step during the simulation.
Using coeffref increased simulation time with about 10x.
I've been thinking of making a single pass of the model and forming pointers directly to the respective location in the coefficient matrix, but this seems a bit dangerous, especially since the LDLT factorisation is run in between.
If the sparsity pattern of your matrix is not changing each time step, then you can directly change the values of the raw data array with valuePtr(). This is extremely simple and can be done in parallel if needed. If you can figure out how to do this in a linear fashion, i.e.
SparseMatrix<double> A;
for(int i = 0; i < n; i++)
A.valuePtr()[i] = ...
then it will stupid fast (something to do with avoiding cache misses and other black magic). As for the previous comment that the LDLT factorization will not change, that is true from a theoretical standpoint. However, according to the Eigen documentation:
"In factorize(), the factors of the coefficient matrix are computed. This step should be called each time the values of the matrix change. However, the structural pattern of the matrix should not change between multiple calls."
https://eigen.tuxfamily.org/dox/group__TopicSparseSystems.html
I think this is because the factors are stored within the solver object, though I could be wrong. A test should be pretty easy to confirm one way or another. That said, I think you have to call factorize() after you change the values. Still though, you can save considerable time by only calling the analyzePattern() routine once.

Calculating determinant of Matrix in C++ without creating submatrices

Is there a way to determine determinant of given matrix in C++ using only one variable (first loaded matrix) and in next recursion functions using only a reference for that matrix?
How to use coordinates of elements in matrix to determine determinants of submatrices of given matrix without creating them as matrices, just using elements in first matrix and their coordinates? Can that be done using recursion or recursion should not be used?
If you're trying to calculate a determinant for any matrix of size larger than 3x3 using Cramer's Rule, you're certainly doing something wrong. Performance will be terrible.
Probably the easiest approach for you to think your way through is to use row reduction to make it into an upper triangular matrix. Finding the determinant of an upper triangular matrix is easy - just multiply down the diagonal. As for the rest, just multiply by the constant factors that you used and remember that every swap is a -1.

Replacing sparse matrix inserting operation in Matlab by C++

I am using a optimization toolbox in Matlab R2016a. But it runs very slow. I find that the main reason is the sparse matrix indexing operation when the size of sparse matrix becomes more than 100000.
In a function of the toolbox, a sparse matrix Jcon is allocated space firstly .
Jcon = spalloc(nrows,ncols,nnonzeros);
Then some other code calculate something like derivatives. In the end some new enties are inserted into Jcon using the following code
Jcon(link_row(ii),col0Right) = DLink.x0_right(ii,jj);
ii and jj are loop variables. The right hand side is usually colume vactor with 4 to 30 rows. The size of Jcon may also change during the inserting operation.
How can I improve the inseting part? Is it possible to use C++ to replace the sparse matrix inserting? Will it be quiker?

Initializing diagonal matrix in opencv, C++

I am writing smoothing spline in C++ using opencv.
I need to use sparse matrix (like in MATLAB), i.e. large matrix which consists of zeros and a few non-zero diagonals. I use Mat matrices for this purpose, because I want to be able to multiply them, transpose them, etc.
Is there exist some elegant way to initialize such matrix, without processing it element after element?
There is a function called Mat::diag, but this creates a column matrix, it is not what I need. Is it possible to convert this to normal matrix? The most similar thing to what I need is Mat::eye, but I need to initialize more than one diagonal, in addition, I have different numbers in same diagonal, so I cannot use Mat::eye.
Thank you!
I solved myself: :)
Mat B = Mat::zeros(3, 3, CV_8UC1);
Mat C = B.diag(0);
C.at<unsigned char>(0) = 64;
C.at<unsigned char>(1) = 64;
C.at<unsigned char>(2) = 64;
Mat::diag is dynamic, so it works.
You can initialize with Mat::eye and multiply by a 1 by N dimensional matrix containing the diagonal values you want. (Or just set them manually.) If your matrix is large enough that these operations take a significant amount of time you should not be using Mat which is not optimized for sparse matrices.
If your matrices are large enough that the above operations are slow, look here.