Reverse An Array

Category: Arrays

Date: 02-16-2022

Return to Index


 
'Compilable Example:  (Jose Includes)
#Compiler PBWin 9, PBWin 10
#Compile EXE
#Dim All
%Unicode=1
'#Debug Display On
'#Debug Error On
#Include "Win32API.inc"
%iLoopMax = 100000
Global hDlg As Dword, qFreq, qStart, qStop As QUAD, DeltaTime As Single
 
Function PBMain() As Long
   Dialog New Pixels, 0, "Reverse Array Elements",300,300,250,200, %WS_OverlappedWindow To hDlg
   Control Add Button, hDlg, 100,"SWAP Array Elements", 50,10,140,20
   Control Add Button, hDlg, 200,"SWAP Element Pointers", 50,40,140,20
   Control Add Button, hDlg, 300,"PEEK", 50,70,140,20
   Control Add Button, hDlg, 400,"ASM_Paul", 50,100,140,20
   Control Add Button, hDlg, 500,"ASM_Hutch", 50,130,140,20
   Control Add Button, hDlg, 600,"Array Sort_Nathan", 50,160,140,20
   Dialog Show Modal hDlg Call DlgProc
End Function
 
CallBack Function DlgProc() As Long
   Local i As Long
   Static myArray() As Long, ParentArray() As Long
   Select Case Cb.Msg
      Case %WM_InitDialog
         QueryPerformanceFrequency qFreq
         ReDim myArray(1000), ParentArray(1000)
         For i = 0 To 1000 : myArray(i) = i : ParentArray(i) = i : Next i  'fake data
      Case %WM_Command
         Select Case Cb.Ctl
            Case 100 :   Reverse_SWAP_ArrayElements(myArray())
            Case 200 :   Reverse_SWAP_ElementsPointers(myArray())
            Case 300 :   Reverse_PEEK(myArray())
            Case 400 :   Reverse_ASM_Paul(myArray())
            Case 500 :   Reverse_ASM_Hutch(myArray())
            Case 600 :   Reverse_ArraySort_Nathan(myArray(),parentArray())
         End Select
   End Select
End Function
 
Sub Reverse_SWAP_ArrayElements(theArray() As Long)
   Local i,iLoop,iMax As Long
   QueryPerformanceCounter qStart
   For iLoop = 0 To %iLoopMax
      '============================================================
      iMax = UBound(theArray)
      For i = 0 To iMax\2
         Swap theArray(i), theArray(iMax-i)
      Next i
      '============================================================
   Next iLoop
   QueryPerformanceCounter qStop
   DeltaTime = (qStop-qStart)/qFreq
   ? "Reverse_ArrayElements  " + Format$(DeltaTime,"0.###") & " seconds"
End Sub
 
Sub Reverse_SWAP_ElementsPointers(theArray() As Long)
   Local i,iLoop As Long, lp,fp As Long Pointer
   QueryPerformanceCounter qStart
   For iLoop = 0 To %iLoopMax
      '============================================================
      lp = VarPtr(theArray(0))
      fp = VarPtr(theArray(1000))
      For i = 0 To UBound(theArray)\2
         Swap @fp, @lp
         Incr lp : Decr fp
      Next i
      '============================================================
   Next iLoop
   QueryPerformanceCounter qStop
   DeltaTime = (qStop-qStart)/qFreq
   ? "Reverse_ElementsPointers  " + Format$(DeltaTime,"0.###") & " seconds"
End Sub
 
Sub Reverse_PEEK(theArray() As Long)
   Register p1 As Long, p2 As Long
   Local i,temp1,temp2,iLoop As Long, lp,fp As Long Pointer
   QueryPerformanceCounter qStart
   For iLoop = 0 To %iLoopMax
      '============================================================
      lp = VarPtr(theArray(0)) : fp = VarPtr(theArray(UBound(theArray)))
      p1=fp : p2=lp
      For i = 0 To UBound(theArray)\2
         temp1=Peek(Long,p1)
         temp2=Peek(Long,p2)
         Poke Long,p1,temp2
         Poke Long,p2,temp1
         p1 -=4 : p2 +=4
      Next i
      '============================================================
   Next iLoop
   QueryPerformanceCounter qStop
   DeltaTime = (qStop-qStart)/qFreq
   ? "Reverse_Peek  " + Format$(DeltaTime,"0.###") & " seconds"
End Sub
 
Function Reverse_ASM_Paul(theArray() As LongAs String
   Register junk As Long, junk2 As Long
   Local iLoop,LoopLimit As Long, lp,fp As Long Pointer
   QueryPerformanceCounter qStart
   For iLoop = 0 To %iLoopMax
      '============================================================
      lp = VarPtr(theArray(0)) : fp = VarPtr(theArray(UBound(theArray)))
      'p1=fp : p2=lp
      LoopLimit =UBound(theArray)\2
      '   FOR i = 0 TO UBOUND(theArray)\2
      ' temp1=PEEK(Long,p1)
      ' temp2=PEEK(Long,p2)
      ' POKE Long,p1,temp2
      ' POKE Long,p2,temp1
      ' p1 -=4 : p2 +=4
 
      !mov ecx,LoopLimit     'get the loop counter into ecx
      !mov esi,lp            'get the 2 pointers into esi and edi
      !mov edi,fp
      #Align 16
lp1:
      !mov eax,[edi]         'get first item
      !mov edx,[esi]         'get last item
      !mov [esi],eax         'store first item in last place
      !mov [edi],edx         'store last item in first place
      !add esi,4             'increment pointer to first item (4 bytes per long)
      !sub edi,4             'decrement pointer to last item
      !dec ecx               'decrement loop counter
      !jns short lp1         'if no sign (i.e. hasn't gone negative) then loop back for next one
 
      '  NEXT i
      '============================================================
   Next iLoop
   QueryPerformanceCounter qStop
   DeltaTime = (qStop-qStart)/qFreq
   ? "Reverse_Peek  " + Format$(DeltaTime,"0.###") & " seconds"
End Function
 
Function Reverse_ASM_Hutch(arr() As LongAs String
   #Register None
   Local iLoop As Long
   QueryPerformanceCounter qStart
   For iLoop = 0 To %iLoopMax
      '============================================================
 
      Local parr As Dword                 ' array pointer
      Local acnt As Dword                 ' array member count
      Local lbnd As Dword                 ' lower bound of array
 
      lbnd = LBound(arr())                ' get lowest array index
      parr = VarPtr(arr(lbnd))            ' get address of 1st array member
      acnt = ArrayAttr(arr(),4)           ' get the array member count
 
      ! sub acnt, 1                       ' correct acnt for 0 base
      ! mov edi, acnt                     ' load count into EDI
      ! mov esi, parr                     ' address of first string HANDLE in ESI
      ! xor ebx, ebx                      ' zero EBX
      ! mov ecx, edi                      ' copy EDI into ECX
      ! shr ecx, 1                        ' INT divide by 2
 
      ' -------------------------------------------
      ' swap pointers from outer pair to inner pair
      ' -------------------------------------------
lbl0:
      ! mov eax, [esi+ebx*4]
      ! mov edx, [esi+edi*4]
      ! mov [esi+ebx*4], edx
      ! mov [esi+edi*4], eax
      ! add ebx, 1
      ! sub edi, 1
      ! sub ecx, 1
      ! jnz lbl0
 
      '============================================================
   Next iLoop
   QueryPerformanceCounter qStop
   DeltaTime = (qStop-qStart)/qFreq
   ? "Reverse_Peek  " + Format$(DeltaTime,"0.###") & " seconds"
End Function
 
Sub Reverse_ArraySort_Nathan(theArray() As Long, pArray() As Long)
   Local i,iLoop As Long
   QueryPerformanceCounter qStart
   For iLoop = 0 To %iLoopMax
      '============================================================
      If i Mod 2 = 0 Then
         Array Sort pArray(), TagArray theArray(), Descend
      Else
         Array Sort pArray(), TagArray theArray(), Ascend
      End If
      '============================================================
   Next iLoop
   QueryPerformanceCounter qStop
   DeltaTime = (qStop-qStart)/qFreq
   ? "Reverse_ArraySort_Nathan  " + Format$(DeltaTime,"0.###") & " seconds"
End Sub
 
'gbs_00900
'Date: 03-10-2012


created by gbSnippets
http://www.garybeene.com/sw/gbsnippets.htm