- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

I have a vector, REAL(4)::V(1000). Say that the largest one happens to be V(123). I need to re-order the values so that V begins with the largest, i.e. Vnew(1) = Vold(123)

Vnew(2) = Vold(124)

;

Vnew(878) = Vold(1000)

Vnew(879) = Vold(1)

Vnew(880) = Vold(2)

:

Vnew(1000) = Vold(122)

That is, the sequence is to remain but the starting point must shift (it is NOT a matter of sorting in numerical order). Of course this can be done in an elementary straightforward manner by creating a copy, say Vaux, reassigning every element in a loop, and then copying Vaux back to V. I suspect there is a better way. Can anyone suggest an optimal algorithm, reducing both the memory required and the execution time?

Link Copied

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

You could mess with pointers maybe but it isn't that big I would do a couple of block copies and a move_alloc rather than copying everything twice.

subroutine order implicit none integer, parameter :: vsize = 1000 integer :: ip1, isz, l1, istat real, allocatable :: V(:), Vtmp(:) allocate(V(vsize), stat = istat) if (istat /= 0) stop 'poo!' do l1 = 1 , vsize ! fill V V(l1) = 1.0*l1 enddo ip1 = 123 ! the pivot point in V isz = vsize - ip1 + 1 ! size of the lower chunk allocate (Vtmp(vsize), stat = istat) if (istat /= 0) stop 'poo!' vtmp(1:isz) = V(ip1:vsize) vtmp(isz+1:vsize) = V(1:ip1-1) call move_alloc(Vtmp, V) end subroutine order

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

You can simply do the following using the intrinsic CSHIFT

V = cshift( V, shift=maxloc(V, dim=1)-1 )

Note though MAXLOC returns "a value equal to the first element of MAXLOC .."

CSHIFT is very efficient for rank-one arrays.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

FortranFan wrote:

You can simply do the following using the intrinsic CSHIFT

V = cshift( V, shift=maxloc(V, dim=1)-1 )Note though MAXLOC returns "a value equal to the first element of MAXLOC .."

CSHIFT is very efficient for rank-one arrays.

Certainly concise but that would surely create temporaries and data (2?) data copies?

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

cshift looks a useful function! Another bit of learning! I would guess that will copy into a temp and then copy the temp back to the original but that isn't really a penalty if the data size is not huge.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

andrew_4619 wrote:

.. I would guess that will copy into a temp and then copy the temp back to the original but that isn't really a penalty if the data size is not huge.

With array transformations, one might as well as employ intrinsics as much as possible: if one can do better than Intel Fortran, then bring it up with Intel to improve their implementaton.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

FortranFan wrote:

With array transformations, one might as well as employ intrinsics as much as possible: if one can do better than Intel Fortran, then bring it up with Intel to improve their implementaton.

Yes I agree with that, in a bored moment later in the week I might make some tests for my own amusement and report back if there is anything of interest.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page