I need to transpose a 3D matrix in Fortran. I have a 3d array: V(111,222,333); I need to transpose it to V(333,111,222). Is there any function to do that in Fortran?
I hesitate to disagree with #IanBush and perhaps what follows is neither easy nor clear. The following statement will return a permutation of the array V. If I have got it right then the element at V(i,j,k) is sent to V_prime(k,i,j).
V_prime = RESHAPE(source=V, shape=[size(V,3),size(V,1),size(V,2)], order=[2,3,1])
Whether this creates the permutation OP asks for is a bit unclear, I'm not aware that there is a single definition of the transpose of an array of rank other than 2. Changing the order will produce different permutations.
This question is probably a duplicate of Fortran reshape - N-dimensional transpose. It is certainly worth reading the answers to that question which explain the use of reshape with order very well.
There is no routine that will do this simply. I would write some loops, that is often the easiest and clearest way.
Related
I want to multiply two 2D arrays element-wise "vertically" so that the resulting array is 3D:
Illustration
Is this possible without much trouble? Thanks in advance for help.
I googled and the only thing that might be purposeful but seems very laborious to me is numpy.reshape
I know a similar question is already asked here for example:
Malloc a 2D array in C
However, my question is not how to create one but rather if I should prefer to use for a mathematical 2D matrix a "real" 2D array (with pointers of pointers) or rather a flattened 1-dimensional array with proper indexing.
I think the only case it can be important is when you are doing operations that depends on the neighbors of the matrix. In this case, using a 2D matrix is a bit better because it avoids cache misses.
This is specially important for problem solutions that use dynamic programming optimization .
I believe it can also be important for image processing, where many operations are applied in a rectangle of pixels.
This code fragment:
real*8 a(20,5,2)
real*8 b(5)
real*8 c(20,5,2)
! define a vals ....
! define b vals ....
c(1:20, :, 1:2) = a(1:20,:,1:2)*b
won't compile because b doesn't have the same shape as a or c. I, of course, want the five values of b to match to the 5 values of the middle indices of a and c, but the Fortran compiler doesn't understand this. Is there some way to tell it what I want here? I know I could replicate b in a larger array to match the shape of a and c but that wastes memory. I could also put the whole thing in loops but for the actual code I am trying to write that will be cumbersome. Are there any other possibilities?
I think that Fortran is either preventing you shooting yourself in the foot, or, if you prefer, insisting that you be clear about what array elements you want to multiply. The expression
a(1:20,:,1:2)
is a section of 40 elements for each value of the 2nd index. It's not at all clear what the 5 elements of b are to multiply.
I suspect that you are looking for the spread function which is the one to use to 'uprank' an array. Without clarification it's kind of difficult to propose an appropriate application of spread, perhaps if you explain further you'll get a better answer than this one.
Heck, let's go ahead without clarification ...
I interpret OP's intention to be to compute the elements of c thusly:
DO ix = 1,5
c(:,ix,:) = a(:,ix,:)*b(ix)
END DO
which can be replaced by
c = a * SPREAD(SPREAD(b,dim=1,ncopies=20),dim=3,ncopies=2)
I've given this only very limited testing, the lesson is perhaps to follow #ptb's advice to stick to do loops.
I am quite new to vba coding. I have written a code which reads some data generates a matrix and a vector inverts the matrix and then multiples the inverted matrix with the vector, so nothing big. But now I want that the elements of the matrix and vector are strings or symbols. I hope that i will be able to get a more general solution. Is this somehow possible? Both objects are arrays.
The stringe i use do not have numerical values. In other words I am looking for a oppertunity to calculat with symbols like an algebra program like mathematica or maxia does.
I'm trying to check if an 1D array of integers A contains or not, at every one of it's size(A) positions, any of the elements of the set of integers S (also a 1D array), with the general case of size(S) > 1.
The easy and obvious way is to do the following nested loop:
DO i = 1, size(A)
DO j = 1, size(S)
IF(A(i) == S(j)) ** do something **
ENDDO
ENDDO
The problem is that, for large arrays A and S, this process is very inefficient. Is there an intrinsic FORTRAN subroutine or function that does this faster? Or any other method?
I've tried to do the following, but it doesn't want to compile:
DO i = 1, NNODES
IF(A(i) == ANY(S)) ** do something **
ENDDO
The error message that appears is the following: "error #6362: The data types of the argument(s) are invalid." I'm using VS2010 with Intel Parallel Studio 2013.
The expression
A(i) == ANY(S)
has an integer on the lhs and a logical on the rhs. We'll have none of that C-inspired nonsense of regarding those as comparable types in Fortran thank you very much. Actually, it's worse than that, any returns a logical but takes an array of logicals on input, so any(array_of_int) won't compile.
You could try
ANY(S==A(i))
instead. That should give you a compilable solution.
Now, as for efficiency, you're first snippet is O(n^2). You can do better, asymptotically. Sort both arrays and scan them in tandem, which is O(n + n log n) or something similar. If you need help coding that up, update your question, though I suspect it's already been asked and answered here on SO.
I strongly suspect, and you can check if you care to, that using any inside a single (explicit) loop will also be O(n^2) -- since any has to operate on the most general cases I can't see any realistic alternative to it scanning the array -- another loop in other words.
In addition to High Performance Mark's answere, when you scan the sorted arrays you can, and should, use a binary search algorithm.