Silverfrost Forums

Welcome to our forums

Mirror and shifting of data

10 Mar 2011 1:18 #7894

Hello,

Here is my original function http://s2.postimage.org/28j2bh57o/curve0.jpg and I am trying to code to generate data to create this mirrored and shifted function as in this figure http://s3.postimage.org/l2e28nic/curve1.jpg

To further clarify, my array which contains, x y 1 10.8 2 10.0 3 9.1 4 8.0 5 6.8 6 6.0 7 5.2 8 4.3 9 3.0 10 0.0

and I am trying to make a new array like,

x y 1 0.0 2 3.0 3 4.3 4 5.2 5 6.0 6 6.8 7 8.0 8 9.1 9 10.0 10 10.8 11 10.8 12 10.0 13 9.1 14 8.0 15 6.8 16 6.0 17 5.2 18 4.3 19 3.0 20 0.0

Here is my code which is giving error,

real, dimension (100) :: oldvalue
real, dimension (200) :: newvalue
real :: shift = 3. 
n=100

do i = 1,n
newvalue (n+i) = oldvalue(i)+shift
end do

do i = 1,n
newvalue (n-i) = oldvalue(i)+shift
end do

Any help is appreciated.

Thanks!

10 Mar 2011 5:33 #7895

May be, the last part of your code should be like this:

do i = 1,n 
newvalue (n-i+1) = oldvalue(i)+shift 
end do

Then, the index of newvalue goes from 1 to 100 instead of 0 to 99.

Regards - Wilfried

10 Mar 2011 5:40 #7896

This solved the problem.

do i = 1,length
newcore(i) = core(length-i+1)
end do


do i = 1,length
newcore(length+i) = core(i)
end do

Many thanks for the response![/code]

11 Mar 2011 12:03 #7897

You may like to consider the following alternatives, using a DO loop or array syntax to achieve what you want. I'm not sure if any is better than the other, as they all achieve a result.

  call do_syntax
!
  call array_syntax
  end

  subroutine do_syntax
  integer*4 list(4), new_list(8), length, i
!
  length = size(list)
  list   = (/ 1, 2, 3, 4 /)
!
  do i = 1,length
     new_list(length-i+1) = list(i)
     new_list(length+i)   = list(i)
  end do
  write (*,'(20i4)') new_list
!
  do i = 1,length
     new_list(i)          = list(i)
     new_list(length+i)   = list(length-i+i)
  end do
  write (*,'(20i4)') new_list
!
  end 

  Subroutine array_syntax
  integer*4, allocatable :: list(:), new_list(:)
  integer*4 length, i
!
  length = 5
  allocate (list(length))
  allocate (new_list(length*2))
!
  forall (i=1:length) list(i) = i*2-1
  new_list(1:length)          = list(1:length)
  new_list(length+1:length*2) = list(length:1:-1)
  write (*,'(20i4)') new_list
!
  forall (i=1:length) list(i) = (length-i)*2+1
  new_list(1:length)          = list(1:length)
  new_list(length+1:length*2) = list(length:1:-1)
  write (*,'(20i4)') new_list
!
  new_list = 0
  forall (i=1:length) 
    new_list(i)        = (length-i)*2+1
    new_list(length+i) = i*2-1
  end forall
  write (*,'(20i4)') new_list
!
  end 
11 Mar 2011 2:20 #7899

Alternatively, if X is actually the array position, then you could just calculate an alternative array subscript to pull out the Y value as in:

Let n = number of entries in original array 'y' i = new array position j = equivalent array position in first array Array y is dimensioned to n

dimension y(10)
data y/10.8, 10.0, 9.1, 8.0, 6.8, 6.0, 5.2, 4.3, 3.0, 0.0 /

n=10
do i=1,n*2
  print *,i,y_mirror(y, n, i)
enddo
end

real function y_mirror(y, n, i)
dimension y(n)
j = abs(i-1) - int( (i-1) / n ) + 1
y_mirror = y( j )
end

and if you want to carry on outside of the range n*2, then the function becomes:

real function y_mirror(y, n, i_input)
dimension y(n)
i = mod( (i_input-1), n*2 ) + 1
j = abs(i-1) - int( (i-1) / n ) + 1
y_mirror = y( j )
end

Hope this helps. Ian

12 Mar 2011 11:53 #7903

Ian,

Your code reminds me of JDATE. (I'll understand that integer code one day.)

I'd prefer a simpler form of j=, possibly: j = min (i, 2*n+1-i) ! valid for i in range 1:2n

or more simply you could use an IF

IF (i > n) then j = 2*n+1-i else j = i end if

I've been coming back to code I wrote years ago and now want it to be easier to understand. It saves time, especially if it needs changeing. Those old integer expressions are not easy to modify.

John

12 Mar 2011 7:27 #7908

Well done John, it is getting simpler all the time. And yes, coming back to old code can be tricky. I think that good commenting is the answer. Once when a couple of us tried to delve into some Z80 assembler, written by someone else who had left the company, we found it was fully commented. Unfortunately one line of code was commented with the phrase 'Old Indian trick' - very helpful I don't think. Of course, you can point out that my miserable attempt avoided useful comments, but it was just intended to take the subject in another direction.

Actually, If you look at the original post, 10.8 is the first element in the input array and is required to be at the 10th and 11th position in the output, your equation does not do this inversion. It would need to be:

j = n+1 - min(i, 2*n+1-i)

No doubt you can simplify this equation as I've just run out of energy for today.

The if-then-else version would just need:

j=n+1-j

adding after the end statement or including in each equation.

Regards Ian

Please login to reply.