Summation in a loop in fortran - arrays

lets say I have the following array: [1,2,3,4,5,6,7,8,9,10]
I need to define a new array in a way that:
for i=1, the first element of this new array will have the sum of only the first element (so returns the first element of the array)
for i=2, the second element of this array has the sum of the first two elements. etc...
then I need to fill each sum in this array.
Any idea how to do it? I'm new to Fortran and cant figure out how to do it, maybe there is a function to do it.

The following does what you want. Instead of using implied-do loops, you could use explicit loops.
program addup
implicit none
integer, allocatable :: a(:), b(:)
integer i, n
n = 10
a = [(i,i=1,n)]
b = [(sum(a(1:i)),i=1,n)]
print '(10(I0,1x))', a
print '(10(I0,1x))', b
end program addup

Related

How do I iterate through matrix elements matlab

I have the task of creating a piece of matlab code that uses the sieve of Eratosthenes to find the list of prime numbers up to N. I have created a loop that finds the non primes and then finds the index value of them in the list of 2 to N. How do I get my program to take these index values element by element and set the corresponding positions in my zero matrix to one?
Also for my assignment I cannot use the in built isprime functions.
My code so far:
function [p,c] = sieve(N)
N = input('Please type an integer greater than 1: ');
a = ones(1,N); %Non-primes are set to 0
for k = 2:N
How does k:k:end work, I'm guessing it adds k until it reaches N.
Thanks
Assuming your matrix of zeros is called "numbersthatareprime" and your prime indices are called "primeindices":
numbersthatareprime(primeindices)=1
That's just a matter of using your array to index into your vector. As such, create a vector of all zeros that is N in length, then assuming you have the list of prime numbers up to N which is called prim, just do:
vec = zeros(1, N);
vec(prim) = 1;
OK
As OP may still be confused, I'll just give a new answer (not dissimilar to my previous wrong one)
x=zeros(100,1);
for i=2:100;
x(2*i:i:end)=1;
end; find(~x)
You just need to go from 2*i rather than i....
You don't really need a matrix. Just a list of values!
X=zeros(10000,1);
for i=2:100
X(i:i:end) = 1
end
Here, the indexing i:i:end means
[2,4,6,8,...] when i==2
[3,6,9,...] when i==3
etc
So it sets all the multiples of 2, then all the multiples of 3 etc., creating your seive.
Note that you only need to go up to sqrt(N).
Then you can just do find(X) to get the primes!

Unable to do vector division (every element) and append to a new array

I need to append the division between two arrays into a new array. But the same value being iteratively stored into the new array.
clear; close all;
%Plot G (small - signal gain) vs v (frequency)
%Assume frequency probe region to be thrice the line-width
f=input('Line Width Frequency(in Hz) :');
v=(-3*f):10e10:(3*f);
l=length(v);
g=zeros(1,l);
k=zeros(1,l);
h=ones(1,l);
% Substituing the constants we realize g(v) is a function
% line shaping function
for i=1:l
k(1:i)=((v(1:i)-2.82*10e-4)+((627.95*10e9)^2));
end
g=rdivide(h,k);
You are assigning multiple elements of k at once. Try this:
for i=1:l
k(i)=((v(i)-2.82*10e-4)+((627.95*10e9)^2));
end
or even more simply, this is a great example of a vectorized operation:
k = (v -2.82*10e-4)+((627.95*10e9)^2)); %% works the same as above
k(1:i) is a slice of the array k, containing the elements 1, 2, .. i. So in the last loop iteration, you assign the entire array k(1:l), wiping out the calculations from previous iterations.

Add element to FORTRAN pointer?

I have an array arr in fortran going from 1 to n where I need to test each element against the elements preceding and succeeding (i.e. i against i-1 and i+1) - the problem being elements 1 and n that have n or 1 as predecessor or successor, respectively (i.e. it loops).
Instead of testing the first and last elements separately, I'd rather run a loop like:
do i=1,n
call testi(i-1,i,i+1)
end do
and define a pointer (in order to not use a dummy array and twice the memory) like
arrpointer(0) => arr(n)
arrpointer(1:n) => arr(1:n)
arrpointer(n+1) => arr(1)
to "simulate" the loop in my array. (Note that each array element is a vector - arr(i)%vec(1:m) )
The above does not work as each new definition of the pointer will overwrite the previous. So the question arises:
Is there any way to actually add an element to a pointer array without deleting the previous definitions?
PS:
As current workaround, I use an allocatable type array with the pointers:
type :: pointerarray
real, pointer :: elementpointer(:)
end type pointerarray
type(pointerarray), allocatable :: arrpointer(:)
arrpointer(0)%elementpointer => arr(n)
do i=1,n
arrpointer(i)%elementpointer => arr(i)
end do
arrpointer(n+1)%elementpointer => arr(1)
while replacing the loop as below does not work:
arrpointer(1:n)%elementpointer => arr(1:n)
However there might be a simpler way of which I am not aware, as type arrays for the pointers again make the code not as nicely readable.
I don't think there's a way to do this with pointers the way you envision. Instead, I recommend using an integer array dimensioned 0:N+1 that map to the desired 1:N range. For example:
integer :: i(0:N+1), j
real :: a(N)
! -- Setup
do j=1,N
i(j) = j
enddo
i(0) = N
i(N+1) = 1
! -- Then you can do:
do j=1,N
! call mysub(a(i(j-1)), a(i(j)), a(i(j+1)))
enddo
Alternatively, you could use a function to define i(j).
I don't have Fortran on this machine so haven't tested this. It's also not entirely clear what OP's testi routine does. So, this is not a complete answer, but might provide some useful (or useless) hints at a pointerless solution.
Don't forget the intrinsic function chsift. One way to perform, say, a one-sided difference calculation on an array would be to write
arrdiff = arr - chsift(arr,1)
cshift shifts elements from one end of the array to the other unlike its cousin eoshift which performs an end-off shift. Of course chsift is likely to require the creation of a temporary of the same size as the array (in theory it could be done without a temporary, in practice it always seems to use one) so may be unappealing on performance and memory usage grounds.

Saving individual arrays from a loop in VBA

So I have an array x(i,j) which is inside a loop k = 1 to n, where n is set by the user. It updates every time I go to the next k. I was wondering if it's possible to save each of the arrays created in the loop to the memory so I can recall them at another time?
So for example, I was thinking I could do something along the lines of:
For k = 1 to n
...
SavedArray(k) = x(i,j)
...
next k
So I could recall, say for example, SavedArray(58) which would have been the 58th iteration of the loop.
Is this feasible?
Thanks for your time.
It depends what is X, and what you wish to save.
If X(i,j) is just Integer so just make a new array and save it : MyArr(k) = X(i,j)
If X(i,j) is array (so X is 2D of 1D array ~ 3D) -you can use Array of Arrays to save it.
To simplify the solution you can create a new type, let say:
Public Type typeArray
X(1 To 10) As Integer
Y(1 To 10) As Integer
End Type
And Declare:
Public SavedArray(1 To 10) As typeArray
Now you can use it as you wish.

Fortran equivalent to matlab find - application to slicing matrix without memory duplication

I use the command find quite a lot in matlab, and I wonder how to translate this smartly in fortran to extract a slice of an array. In matlab you can slice with either logicals or indexes, but in fortran you need indexes to slice. I'm aware of the intrinsic subroutines pack et al, but have never used them. Also, since I'm dealing with big matrices, I would like to avoid duplicating memory. I want the sliced matrix to be manipulated within a subroutine. I've read somewhere that slices of array were not duplicated. I don't know how this the slicing in done in matlab though. I'm puzzled also because in matlab some allocations are transparent to you.
I'd like to know how to reproduce the examples below, and make sure I'm not duplicating stuff in memory and that it's actually elegant to do so. Otherwise, I would forget about slicing and just send the whole matrix(since it's by reference) and loop through an index array I...
Matlab example 1: simply reproducing find
v=[1 2 3 4];
I=find(v==3);
Matlab example 2:
m=rand(4,4);
bools=logical([ 1 0 0 1]);
I=find(bools==1);
% which I could also do like:
I=1:size(m,1);
I=I(bools);
for i=1:length(I)
% here dealing with m(I(i)),:) and do some computation
% etc.
Example 3: just call a subroutine on m(I,:) , but using directly booleans for slicing
foo( m(bools, :) , arg2, arg3 )
In advance thank you for your help!
Fortran doesn't have an exact match for Matlab's find but you can generally use either where or forall, and sometimes both, to replace its functionality.
For example, given an array v such as you have in your first example, the Fortran statement
where (v==3) do_stuff
will operate only on the elements of v which are equal to 3. This doesn't get you the indices of those elements as find does, but much of the use of find is for selecting elements for having stuff done to them, and in most of those cases the where construct is applicable.
Given v as before, and an index array ix which, in Fortran, is an array of logicals like this:
[.true., .false., .false., .true.]
you can use ix, so long as it is the same shape as v, in masked array assignments such as
where (ix) v = some_value
ix doesn't have to be an array of logicals, it can be an array of any type, if it were an array of reals you might have an expression such as
where (ix>=0.0) v = some_value
I don't think that any of the current Fortran compilers make copies of arrays to implement where constructs. I'll leave you to read about the forall construct.
Don't forget, either, that you can use arrays as indices for Fortran arrays, so the expression
v([1,3]) = 0
sets elements 1 and 3 of v to 0. You can, of course, use multiple array indices if your array has rank greater than 1.
When you start using this sort of indexing to pass non-contiguous sections of an array to a sub-program, then you have to start worrying about copying into temporary arrays (if that's the sort of thing that you want to worry about). I believe that compilers may make temporary copies if you do something like
call my_subroutine(array(1:12:3, 2:12:4))
to enable the subroutine, which does not know the indices of the elements of the array section at run-time, to operate on what it 'sees' as a contiguous array.
You can use "pack" with an implied do loop:
I = pack([(j,j=1,size(v))],v==3)
Bellow, in FORTRAN CODE, is an example of a subroutine that makes the equivalent of find in matlab or scilab. In the examples below, we want to (a) find the position of the vector where the vector is equal to 22 (b) find the positions of even numbers in a vector
PROGRAM Principal
REAL*8 A(8)
INTEGER n, npos, pos(8)
n=8
A = (/ 19, 20, 21, 22, 23, 24, 25, 26 /)
! Find the positions of vector A that is equal to 22
CALL FindInVector(n,A==22,npos,pos)
WRITE(*,*) pos(1:npos)
! Find the positions of vector A that contains even numbers
CALL FindInVector(n,ABS(A/2.d0-INT(A/2.d0))<1.d-2,npos,pos)
WRITE(*,*) pos(1:npos)
END PROGRAM Principal
!________________________________________________________________
! Subroutine that find positions of a vector of logicals TF (True or False). The first npos elements contains the response.
SUBROUTINE FindInVector(n,TF,npos,pos)
! Inlet variables
INTEGER,INTENT(IN):: n ! Dimension of logical vector
LOGICAL,INTENT(IN):: TF(n) ! Logical vector (True or False)
! Outlet variables
INTEGER npos ! number of "true" conditions
INTEGER pos(n) ! position of "true" conditions
! Internal variables
INTEGER i ! counter
INTEGER v(n) ! vector of all positions
pos = 0 ! Initialize pos
FORALL(i=1:n) v(i) = i ! Enumerate all positions
npos = COUNT(TF) ! Count the elements of TF that are .True.
pos(1:npos)= pack(v, TF) ! With Pack function, verify position of true conditions
ENDSUBROUTINE FindInVector
I think a simpler version is possible, see the subroutine below. The example shows how to find the values smaller than 0.1 in array x.
program test
real, dimension(:), allocatable :: x
integer, dimension(:), allocatable :: zeros
x=[1.,2.,3.,4.,0.,5.,6.,7.,0.,8.]
call find_in_array(x<0.01,zeros)
write(*,*)zeros
contains
subroutine find_in_array(TF,res)
! Dummy arguments
logical, dimension(:), intent(in) :: TF ! logical array
integer, dimension(:), allocatable, intent(out) :: res ! positions of true
! elements
! Local arrays
integer, dimension(:), allocatable :: pos
pos=[(i,i=1,size(TF))]
!pos=[1:size(TF)] ! valid on Intel compiler
res=pack(pos,TF)
end subroutine find_in_array
end program test

Resources