Your program example could be improved substantially, as you have done a masked search 2,000 times.
I have modified your code to:
- use a parameter NUM rather than 1000 for a test.
- included a use of ISORT@ to show an alternative solution.
- I do not know why you used the line 'MAX = MAXVAL(ARRAY, MASK = ARRAY ⇐ I)' as MAXVAL returns a scalar.
- MAXVAL can be replaced by MAXLOC as it does the same search.
- included some timing to see how long both approaches take.
You should try a larger value of num to see how dramatically different the run time is between the 2 approaches, say a value of num = 100,000 or 1,000,000 will show a big difference, if you have the time to wait.
Intrinsic procedures for searching still have to do similar searching operations as a procedure you could write yourself. They are not much faster.
I hope this example is of use.
PROGRAM SORT_ARRAY
!
! ARRAY IS THE ORIGINAL ARRAY
! MM IS AN INTERMEDIATE ARRAY
! B IS THE FINAL ARRAY SORTED, THAT WILL BE USED
!
implicit none
!
integer, parameter :: num = 100000
!
INTEGER ARRAY(num), MM(num), B(num), G, I, T, NT, i0,i1,i2,i3, k
real*8 x
!
call system_clock (i0)
DO I = 1, num
call random_number (x)
ARRAY(I) = int ( x * real(num) )
END DO
!
! This is a much faster solution, if many ordered values are required
call system_clock (i1)
call isort@ (mm, array, num)
write (*,1000) (array(mm(num-i)),i=0,9)
!
! Now proceed with original scan
call system_clock (i2)
I = MAXVAL (ARRAY)
!
! determine number of scans to make ( = num takes too long )
NT = sqrt (real(num))
if (NT < 20) NT = 20
if (NT > 100) NT = 100
!
DO T = 1, NT ! was 'num'
if (mod(t,num/10) == 0) write (*,*) 'At',T
!
! Why the use of array MM ?, as MAXVAL returns a scalar (rank 1 less than ARRAY)
!! MM = MAXVAL (ARRAY, MASK = ARRAY <= I)
!! B(T) = MM(T)
!
B(T) = MAXVAL (ARRAY, MASK = ARRAY <= I)
!
G = MAXLOC (ARRAY, DIM = 1, MASK = ARRAY .LE. I)
!
I = ARRAY(G)
!
! NOTE: ARRAY(G) could also be used to set B(T)
!zz B(T) = I
!
! ... because it's possible that some values are repeated in ARRAY
! we need to change it to catch other equal values:
ARRAY(G) = ARRAY(G) + 1
! that means that ARRAY is no longer the same as at the beginning
END DO
write (*,1000) (B(i), i=1,10)
call system_clock (i3)
!
! estimate of equivalent number of scan operations to a full sort
k = nint ( real(I2-I1)/real(i3-i2) * real(NT) )
write (*,1002) &
'Set Up data ', (i1-i0),' ticks', &
'Sort search ', (i2-i1),' ticks', &
'Scan search ', (i3-i2),' ticks', &
'Array Size ', num, ' ', &
'Num scans ', NT, ' ', &
'Scans = Sort', k, ' scans'
1000 format (10i8)
1002 format (1x,a,i8,a)
END PROGRAM