I am trying to do a 1D IFFT transformation of a complex input array with a conjugate even symmetry, with z(1) and z(N/2+1) being real. The total size of the array is N=256. If I prepare the IFFT like the following:
stat = DftiCreateDescriptor( desc_handle, DFTI_DOUBLE, DFTI_REAL, 1,256)
stat = DftiSetValue(desc_handle, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX)
stat = DftiSetValue(desc_handle, DFTI_PLACEMENT, DFTI_NOT_INPLACE)
stat = DftiComputeBackward(desc_handle, X_in, M_out)
... where X_in has the conjugate symmetry even described above. That means that M_out is expected to be a mathematical real array in the sense that if:
real(dp) :: M_out(N+2)
then the expected real fortran array with have every other element equal to zero.
complex(dp) :: M_out(N/2)
then the expected complex fortran array will have N/2 size with the imaginary part being zero.
However the results I get are not real after doing the above. It is like the routines do not understand that the input complex fortran array does not have the conjugate even symmetry. Why is that? Do I have to add any other preference parameters to ensure the structure of the input is read correctly?
In this example forward domain is real and backward domain is conjugate even with complex storage. Therefore MKL expects that X_in is of type Complex[] and M_out is of type Real[]. Results are real.
I suspect, that you supplied a complex array as M_out. Then this array is interpreted as Real[] and contains real results of the backward transform. No zeroes for imaginary part are inserted.
Related
I'm trying to understand the documentation for sgemm as I am transitioning code from using this library to a different library.
The function prototype is
sgemm ( character TRANSA,
character TRANSB,
integer M,
integer N,
integer K,
real ALPHA,
real, dimension(lda,*) A,
integer LDA,
real, dimension(ldb,*) B,
integer LDB,
real BETA,
real, dimension(ldc,*) C,
integer LDC
)
I am having trouble understanding the role or LDA and LDB. The documentation says
LDA is INTEGER
On entry, LDA specifies the first dimension of A as declared
in the calling (sub) program. When TRANSA = 'N' or 'n' then
LDA must be at least max( 1, m ), otherwise LDA must be at
least max( 1, k ).
What does it mean that it specifies the first dimension of A? Is this like switching between row and column major? Or is this slicing the tensor?
LD stands for leading dimension. BLAS is originally a library of Fortran 77 subroutines and in Fortran matrices are stored column-wise: A(i,j) is immediately followed in memory by A(i+1,j), which is opposite of C/C++ where a[i][j] is followed by a[i][j+1]. In order to access element A(i,j) of a matrix that has dimensions A(LDA,*) (which reads as LDA rows and an unspecified number of columns), you need to look (j-1)*LDA + (i-1) elements from the beginning of the matrix (Fortran arrays are 1-indexed by default), therefore you need to know the value of LDA. You don't need to know the actual number of columns, therefore the * in the dummy argument.
It is the same in C/C++. If you have a 2D array declared as a[something][LDA], then element a[i][j] is located i*LDA + j positions after the start of the array, and you only need to know LDA - the value of something does not affect the calculation of the address of a[i][j].
Although GEMM operates on an M x K matrix A, the actual data may be embedded in a bigger matrix that is LDA x L, where LDA >= M and L >= K, therefore the LDA is specified explicitly. The same applies to LDB and LDC.
BLAS was developed many years ago when computer programming was quite different than what it is today. Memory management, in particular, was not as flexible as it is nowadays. Allocating one big matrix and then using and reusing portions of it to store smaller matrices was the norm. Also, GEMM is extensively used in, e.g., iterative algorithms that work on various sub-matrices and it is faster to keep the data in the original matrix and just specify the sub-matrix location and dimension, so you need to provide both dimensions.
Starting with Fortran 90, the language has array slicing and automatic array descriptors that allow one to discover both the dimensions of a slice and those of the bigger matrix, so if GEMM was written in Fortran 90 or later, it wouldn't be that verbose in respect to its arguments. But even if that was the case, C doesn't have array descriptors, so you'll still have to provide all those arguments in order to make GEMM callable from C. In C++, one can hide the descriptor inside a matrix class, and many math libraries actually do so (for example, Scythe).
I have a huge m by 1 array (m is very large) called X which is a result of Fortran matmul operation. My problem is to store this apparently 2D array into an 1D array Y of size m.
I tried with Y = reshape(X, [[2]]) and this result some elements NaN. Can anyone point me to Fortran commands to do it quickly. The elements of X may be zero or non-zero.
The second argument of reshape (or the one with keyword shape=) is the shape of the function's result. In your call, you have requested shape [2].
An array with shape [2] is a rank-1 array with two elements. You want a rank-1 array with m elements:
Y = RESHAPE(X, [m])
Now, in this case there's no need to use reshape:
Y = X(:,1)
where the right-hand side is the rank-1 array section of X.
When you have Y=reshape(X,[2]), if Y is not allocatable and not of size 2 then you have a problem which may indeed result in your compiler deciding---as it is quite entitled to do---to give you a few NaNs.
Note also that you may not need to reshape your array, depending on how you intend to later use it.
I want to write a subroutine which could be used in 1D or 2D geometry.
Consequently I have variables that will be used only in the latter case.
I wish I could write a declaration section in that style:
real ( kind = double ) :: uleft,vleft,uright,vright
real ( kind = double ) :: distanceinx
real ( kind = double ) :: ...
if (ndim == 2) then
real ( kind = double ) :: ulow,vlow,uup,vup
real ( kind = double ) :: distanceiny
end if
but it doesn't compile.
Is there a syntax to do what I want to do in a proper way ?
A big part of the code will be similar in the two cases (ndim = 1 or 2) so I think that makes sense.
Just leave the variables there and don't use them in 1D. The syntax you propose does not exist and I don't know of any other similar one.
In Fortran 2003 you can also make them allocatable, but that is worth it only for arrays, to save some space.
Do not care about couple of unused bytes on the stack. They can remain unused in 1D.
You could treat the 1D array as a special two-dimensional array with Nx1. Then you could always use the 2D version of your code. You can still check for the length of the second dimension to determine the dimension. This even allows for extension to the third dimension!
Routines/functions like norm2 also work on both types, so this could further simplify your code.
I am a EE, not a code expert, so please bear with me here.
I am using Embarcadero C++ Builder (XE3).
I have an FFT algorithm which does a fair number of operations on complex numbers. I found out that if I bypass Embarcadero's complex math library, and do all the calculations in my own code, my FFT will run about 4.5 times faster. The 4 operations shown here all require an inordinate amount of time.
#include <dinkumware\complex>
#define ComplexD std::complex<double>
ComplexD X, Y, Z, FFTInput[1024];
double x, y;
Z = X * Y;
x = X.real();
y = X.imag();
Z = ComplexD(x,y);
Replacing the multiplication with my own cross multiply cut my execution times in half. My concern however is with the way I am accessing the real and imaginary parts of the input array. I am doing this:
double *Input;
Input = reinterpret_cast<double *>(FFTInput);
// Then these statements are equivalent.
x = FFTInput[n].real();
y = FFTInput[n].imag();
x = Input[2*n];
y = Input[2*n+1];
Doing this cut my execution times in half again, but I don't know if this reinterpret_cast is a wise thing to do. I could change the input array to two doubles instead of a complex, but I am using this FFT in numerous programs and don't want to rewrite everything.
Is this reinterpret_cast OK, or will I have memory problems? Also, is there a way to get the Embarcadero complex math functions to run faster? And finally, although its not terribly important to me, is this reinterpret_cast portable?
This is allowed. Whilst this isn't a standard quote, cppreference has this to say:
For any pointer to an element of an array of complex numbers p and any
valid array index i, reinterpret_cast<T*>(p)[2*i] is the real part of
the complex number p[i], and reinterpret_cast<T*>(p)[2*i + 1] is the
imaginary part of the complex number p[i].
I will look for the quote from the actual standard soon.
From here it says at the bottom of the page:
For any complex number z, reinterpret_cast<T(&)[2]>(z)[0] is the real part of z and reinterpret_cast<T(&)[2]>(z)[1] is the imaginary part of z.
For any pointer to an element of an array of complex numbers p and any valid array index i, reinterpret_cast<T*>(p)[2*i] is the real part of the complex number p[i], and reinterpret_cast<T*>(p)[2*i + 1] is the imaginary part of the complex number p[i]. (Since C++11)
These requirements essentially limit implementation of each of the three specializations of std::complex to declaring two and only two non-static data members, of type value_type, with the same member access, which hold the real and the imaginary components, respectively.
So what you are doing is guaranteed to work in C++11, but not before that. It may still work with your library's implementation, but you need to check that your library's implementation does not define any more non-static data members as per the third paragraph.
Consider the following:
program main
integer, parameter :: n=10, m=20
integer ints(n,m)
real floats(m,n)
!... initialize ints
! ...
floats=transpose(ints)
!... do stuff with floats
end
looking at the documentation for gfortran, it seems that transpose(ints) will return an integer array which will then be cast to reals. In this operation, the compiler (gfortran) creates a temporary array for the transposed array which seems like a waste (compile with gfortran -O3 -Warray-temporaries -o test test.f90). Also note that if you change the real array "floats" into an integer array, the warning goes away.
Is there a way to do this (for arbitrary types) without generating a temporary array? (I also tried floats(:,:)=transpose(ints) because I read somewhere that it mattered ... ). Does it behave this way with other compilers?
You could try
floats = transpose(real(ints))
but I wouldn't be very surprised if gfortran (or any other compiler) generated a temporary array to implement this. I'd be more surprised if it didn't.
You might also try
forall (J=1:N, K=1:M) floats(K, J) = real(ints(J, K))
Again, I wouldn't be surprised if a compiler created a temporary array to implement this.
do i = 1, n
do j = 1, m
floats(j,i) = real(ints(i,j))
enddo
enddo
You could make your own transpose interface for handling different data types, although it would have to be a subroutine and not a function.
interface transpose_
module procedure transpose_ints_to_reals
end interface
subroutine transpose_ints_to_reals(ints_in, reals_out)
...
end subroutine
call transpose_(ints,floats)