Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Trouble manipulating arrays in Fortran?

Status
Not open for further replies.

chazhang

Technical User
Jul 9, 2009
4
CA
Hi,

I'm not really a programmer and I've been working mostly in Matlab for the last few weeks. Now I need to take my work and translate it to Fortran to integrate it with the rest of the program (which is written in Fortran 77).

I'm just wondering if it's possible to assign the length of the array somewhere in the middle of the program rather than making it an arbitrary long length at the very beginning.

The context is for wavelet transformation where the user can select different types of filters, each having a different length.

Two problems come up by defining the arrays as arbitrarily long:

1. When the filter is arbitrary length, it's difficult to pad the signal appropriately, normally you would have to add n-1 0s to the start of the signal, where n is the length of the filter. In matlab I did:
n = length(filter);
m = length(signal);
paddedsignal = zeros(1,m+n-1);
paddedsignal(1,1:n-1) = zeros(1,1:n-1);
paddedsignal(1,n:m+n-1) = signal(1,1:m);

2. After each iteration of going through the signal, I take the low frequency result and run it through the filter again. Thus each time the size of the input array decreases by a factor of 2(from 16 to 8 to 4 to 2). By making the input array a length of 16 each time (and thus having extra zeros most of the time), it messes up with left shifting, right shifting and convolving. In matlab I did something like:
n = length(input);
output = zeros(1,n/2);

I'm currently using a few obscure tricks to get around parts of the problem(passing the iteration counts to define which values within arrays I pull). I'm wondering if there is a way to make this a much more strait forward and easily manipulated program.

Thanks a bunch in advance for any help.
You can probably tell by my lack of technical jargon I've never taken a programming course before.
 
I'm just wondering if it's possible to assign the length of the array somewhere in the middle of the program ...
Yes, you can use allocatable array
 
Thanks. But now I'm having trouble because I keep triggering breakpoints on my allocation lines, not exactly sure why it occurs. Here's an instance of the code (comments removed):

subroutine wavelettransform(in,filt,out)
real in(16), out(16)
real, allocatable :: filt:))
real, allocatable :: beta:)), alpha:)), putinfilter:))
integer i,j,k,n
allocate (beta(16))
allocate (putinfilter(16))
putinfilter = in

do i = 3, 1, -1
n = 2**i
deallocate (alpha) !breaks here
allocate (alpha(n)) !and here if the above is commented out
call hifreqoutput(putinfilter,filt,alpha)
j = (2**i) + 1
k = 2**(i+1)
out(j:k) = alpha

deallocate (beta)
allocate (beta(n))
call lofreqoutput(putinfilter,filt,beta)
deallocate (putinfilter)
allocate (putinfilter(n))
putinfilter = beta
enddo
out(1:2) = beta(1:2)
return
end
 
Hi chazhang,
In your original code you tried to deallocate the array alpha before you allocated it, therefore you got an error - I fixed it with condition, which checks if it's allocated.

Here is the skeleton of corrected code, which compiles and runs, but you should add the functionality you need
wawelet.f90
Code:
[COLOR=#a020f0]program[/color] wawelet
  [COLOR=#0000ff]! main program[/color]
[COLOR=#2e8b57][b]  real[/b][/color]:: input([COLOR=#ff00ff]16[/color]), output([COLOR=#ff00ff]16[/color]) 
[COLOR=#2e8b57][b]  real[/b][/color], [COLOR=#2e8b57][b]allocatable[/b][/color] :: filter(:)

  [COLOR=#804040][b]write[/b][/color]([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]'calling wavelettransform ...'[/color]
  [COLOR=#a020f0]call[/color] wavelettransform(input, filter, output)
  [COLOR=#804040][b]write[/b][/color]([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]'done...'[/color]
  [COLOR=#0000ff]! [/color]

[COLOR=#a020f0]contains[/color]

[COLOR=#0000ff]! *** Functions/Subroutines ***  [/color]
[COLOR=#a020f0]subroutine[/color] wavelettransform([COLOR=#2e8b57][b]in[/b][/color],filt,[COLOR=#2e8b57][b]out[/b][/color])
[COLOR=#2e8b57][b]  real[/b][/color] :: [COLOR=#2e8b57][b]in[/b][/color]([COLOR=#ff00ff]16[/color]), [COLOR=#2e8b57][b]out[/b][/color]([COLOR=#ff00ff]16[/color]) 
[COLOR=#2e8b57][b]  real[/b][/color], [COLOR=#2e8b57][b]allocatable[/b][/color] :: filt(:)
[COLOR=#2e8b57][b]  real[/b][/color], [COLOR=#2e8b57][b]allocatable[/b][/color] :: beta(:), alpha(:), putinfilter(:)
  [COLOR=#2e8b57][b]integer[/b][/color] i,j,k,n     
  [COLOR=#804040][b]allocate[/b][/color] (beta([COLOR=#ff00ff]16[/color]))     
  [COLOR=#804040][b]allocate[/b][/color] (putinfilter([COLOR=#ff00ff]16[/color]))   
  putinfilter [COLOR=#804040][b]=[/b][/color] [COLOR=#2e8b57][b]in[/b][/color]      
   
  [COLOR=#804040][b]do[/b][/color] i [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]3[/color], [COLOR=#ff00ff]1[/color], [COLOR=#804040][b]-[/b][/color][COLOR=#ff00ff]1[/color]      
    n [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]2[/color][COLOR=#804040][b]**[/b][/color]i
    [COLOR=#804040][b]if[/b][/color] ([COLOR=#008080]allocated[/color](alpha)) [COLOR=#804040][b]then[/b][/color]
      [COLOR=#0000ff]!!! deallocate, only if allocated before !!!    [/color]
      [COLOR=#804040][b]deallocate[/b][/color] (alpha)   [COLOR=#0000ff]!breaks here[/color]
    [COLOR=#804040][b]end if[/b][/color] 
    [COLOR=#804040][b]allocate[/b][/color] (alpha(n))  [COLOR=#0000ff]!and here if the above is commented out      [/color]
    [COLOR=#a020f0]call[/color] hifreqoutput(putinfilter,filt,alpha)
    j [COLOR=#804040][b]=[/b][/color] ([COLOR=#ff00ff]2[/color][COLOR=#804040][b]**[/b][/color]i) [COLOR=#804040][b]+[/b][/color] [COLOR=#ff00ff]1[/color]
    k [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]2[/color][COLOR=#804040][b]**[/b][/color](i[COLOR=#804040][b]+[/b][/color][COLOR=#ff00ff]1[/color])
    [COLOR=#2e8b57][b]out[/b][/color](j:k) [COLOR=#804040][b]=[/b][/color] alpha
       
    [COLOR=#804040][b]deallocate[/b][/color] (beta)   
    [COLOR=#804040][b]allocate[/b][/color] (beta(n))       
    [COLOR=#a020f0]call[/color] lofreqoutput(putinfilter,filt,beta)      
    [COLOR=#804040][b]deallocate[/b][/color] (putinfilter)       
    [COLOR=#804040][b]allocate[/b][/color] (putinfilter(n))      
    putinfilter [COLOR=#804040][b]=[/b][/color] beta
  [COLOR=#804040][b]enddo[/b][/color]
  [COLOR=#2e8b57][b]out[/b][/color]([COLOR=#ff00ff]1[/color]:[COLOR=#ff00ff]2[/color]) [COLOR=#804040][b]=[/b][/color] beta([COLOR=#ff00ff]1[/color]:[COLOR=#ff00ff]2[/color])
  [COLOR=#804040][b]return[/b][/color]
[COLOR=#a020f0]end subroutine[/color] wavelettransform

[COLOR=#a020f0]subroutine[/color] hifreqoutput(putinfilter,filt,alpha)
[COLOR=#2e8b57][b]  real[/b][/color], [COLOR=#2e8b57][b]allocatable[/b][/color] :: putinfilter(:), filt(:), alpha(:)
  [COLOR=#0000ff]! to do[/color]
[COLOR=#a020f0]end subroutine[/color] hifreqoutput

[COLOR=#a020f0]subroutine[/color] lofreqoutput(putinfilter,filt,beta)
[COLOR=#2e8b57][b]  real[/b][/color], [COLOR=#2e8b57][b]allocatable[/b][/color] :: putinfilter(:), filt(:), beta(:)
  [COLOR=#0000ff]! to do[/color]
[COLOR=#a020f0]end subroutine[/color] lofreqoutput

[COLOR=#0000ff]! end of main program[/color]
[COLOR=#a020f0]end program[/color] wawelet
Compile and run
Code:
$ g95 wawelet.f90 -o wawelet

$ wawelet
 calling wavelettransform ...
 done...
 
Or maybe usinge if..else would be clearer
Code:
[COLOR=#a020f0]program[/color] wawelet
  [COLOR=#0000ff]! main program[/color]
[COLOR=#2e8b57][b]  real[/b][/color]:: input([COLOR=#ff00ff]16[/color]), output([COLOR=#ff00ff]16[/color]) 
[COLOR=#2e8b57][b]  real[/b][/color], [COLOR=#2e8b57][b]allocatable[/b][/color] :: filter(:)

  [COLOR=#804040][b]write[/b][/color]([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]'calling wavelettransform ...'[/color]
  [COLOR=#a020f0]call[/color] wavelettransform(input, filter, output)
  [COLOR=#804040][b]write[/b][/color]([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]'done...'[/color]
  [COLOR=#0000ff]! [/color]

[COLOR=#a020f0]contains[/color]

[COLOR=#0000ff]! *** Functions/Subroutines ***  [/color]
[COLOR=#a020f0]subroutine[/color] wavelettransform([COLOR=#2e8b57][b]in[/b][/color],filt,[COLOR=#2e8b57][b]out[/b][/color])
[COLOR=#2e8b57][b]  real[/b][/color] :: [COLOR=#2e8b57][b]in[/b][/color]([COLOR=#ff00ff]16[/color]), [COLOR=#2e8b57][b]out[/b][/color]([COLOR=#ff00ff]16[/color]) 
[COLOR=#2e8b57][b]  real[/b][/color], [COLOR=#2e8b57][b]allocatable[/b][/color] :: filt(:)
[COLOR=#2e8b57][b]  real[/b][/color], [COLOR=#2e8b57][b]allocatable[/b][/color] :: beta(:), alpha(:), putinfilter(:)
  [COLOR=#2e8b57][b]integer[/b][/color] i,j,k,n     
  [COLOR=#804040][b]allocate[/b][/color] (beta([COLOR=#ff00ff]16[/color]))     
  [COLOR=#804040][b]allocate[/b][/color] (putinfilter([COLOR=#ff00ff]16[/color]))   
  putinfilter [COLOR=#804040][b]=[/b][/color] [COLOR=#2e8b57][b]in[/b][/color]      
   
  [COLOR=#804040][b]do[/b][/color] i [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]3[/color], [COLOR=#ff00ff]1[/color], [COLOR=#804040][b]-[/b][/color][COLOR=#ff00ff]1[/color]      
    n [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]2[/color][COLOR=#804040][b]**[/b][/color]i
    [COLOR=#804040][b]if[/b][/color] ([COLOR=#008080]allocated[/color](alpha)) [COLOR=#804040][b]then[/b][/color]
      [COLOR=#0000ff]!!! deallocate, only if allocated before !!!    [/color]
      [COLOR=#804040][b]deallocate[/b][/color] (alpha)   [COLOR=#0000ff]!breaks here[/color]
    [COLOR=#804040][b]else[/b][/color]
      [COLOR=#804040][b]allocate[/b][/color] (alpha(n))  [COLOR=#0000ff]!and here if the above is commented out      [/color]
    [COLOR=#804040][b]end if[/b][/color] 
    [COLOR=#a020f0]call[/color] hifreqoutput(putinfilter,filt,alpha)
    j [COLOR=#804040][b]=[/b][/color] ([COLOR=#ff00ff]2[/color][COLOR=#804040][b]**[/b][/color]i) [COLOR=#804040][b]+[/b][/color] [COLOR=#ff00ff]1[/color]
    k [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]2[/color][COLOR=#804040][b]**[/b][/color](i[COLOR=#804040][b]+[/b][/color][COLOR=#ff00ff]1[/color])
    [COLOR=#2e8b57][b]out[/b][/color](j:k) [COLOR=#804040][b]=[/b][/color] alpha
       
    [COLOR=#804040][b]deallocate[/b][/color] (beta)   
    [COLOR=#804040][b]allocate[/b][/color] (beta(n))       
    [COLOR=#a020f0]call[/color] lofreqoutput(putinfilter,filt,beta)      
    [COLOR=#804040][b]deallocate[/b][/color] (putinfilter)       
    [COLOR=#804040][b]allocate[/b][/color] (putinfilter(n))      
    putinfilter [COLOR=#804040][b]=[/b][/color] beta
  [COLOR=#804040][b]enddo[/b][/color]
  [COLOR=#2e8b57][b]out[/b][/color]([COLOR=#ff00ff]1[/color]:[COLOR=#ff00ff]2[/color]) [COLOR=#804040][b]=[/b][/color] beta([COLOR=#ff00ff]1[/color]:[COLOR=#ff00ff]2[/color])
  [COLOR=#804040][b]return[/b][/color]
[COLOR=#a020f0]end subroutine[/color] wavelettransform

[COLOR=#a020f0]subroutine[/color] hifreqoutput(putinfilter,filt,alpha)
[COLOR=#2e8b57][b]  real[/b][/color], [COLOR=#2e8b57][b]allocatable[/b][/color] :: putinfilter(:), filt(:), alpha(:)
  [COLOR=#0000ff]! to do[/color]
[COLOR=#a020f0]end subroutine[/color] hifreqoutput

[COLOR=#a020f0]subroutine[/color] lofreqoutput(putinfilter,filt,beta)
[COLOR=#2e8b57][b]  real[/b][/color], [COLOR=#2e8b57][b]allocatable[/b][/color] :: putinfilter(:), filt(:), beta(:)
  [COLOR=#0000ff]! to do[/color]
[COLOR=#a020f0]end subroutine[/color] lofreqoutput

[COLOR=#0000ff]! end of main program[/color]
[COLOR=#a020f0]end program[/color] wawelet
 
My mistake! - however you want every time allocate and you need to deallocate before, so the second approach with "else" doesn't match your need, but the first.
:)
 
The first one worked perfectly!

Thanks sooo much for the help!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top