Date: 02-16-2022
Return to Index
created by gbSnippets
'Often, a programmer needs to make a copy of an array. Here are a
'couple of ways to do the trick.
'Primary Code:
'A simple For/Next loop will work just fine:
For i = 0 to UBound(MyArray)
NewArray(i) = MyArray(i)
Next i
'A faster approach is to do a block copy using Peek$/Poke$
Source& = VarPTR(OriginalArray%(1))
Dest& = VarPTR(NewArray%(1))
ArrayLen& = Elements& * 2 'byte length of array
Poke$ Dest&, Peek$(Source&, ArrayLen&) 'copy block
'The PowerBASIC MAT statement works even faster
Mat NewArray() = MyArray()
'Compilable Example: (Jose Includes)
#Compiler PBWin 9, PBWin 10
#Compile EXE
#Dim All
%Unicode=1
Type MyType
x As Long
s As String * 5
End Type
#Include "Win32API.inc"
Global hDlg As Dword, MyArray(), NewArray() As Long
Function PBMain() As Long
Dim MyArray(10000) As Long, NewArray(10000) As Long
Dialog New Pixels, 0, "Test Code",300,300,300,200, %WS_OverlappedWindow To hDlg
Control Add Button, hDlg, 100,"For/Next Loop", 20,20,120,20
Control Add Button, hDlg, 200,"Block Copy", 20,50,120,20
Control Add Button, hDlg, 300,"MAT Copy", 20,80,120,20
Control Add Button, hDlg, 400,"CopyMemory Copy", 20,110,120,20
Dialog Show Modal hDlg Call DlgProc
End Function
CallBack Function DlgProc() As Long
Local i,j,iStart, iEnd As Long
If Cb.Msg = %WM_Command And Cb.Ctl = 100 And Cb.CtlMsg = %BN_Clicked Then
For i = 0 To UBound(MyArray) : MyArray(i) = Rnd(1,1000) : Next i
iStart = GetTickCount
For i = 1 To 100000
For j = 0 To UBound(MyArray)
NewArray(j) = MyArray(j)
Next j
Next i
iEnd = GetTickCount
MsgBox Format$((iEnd - iStart)/1000,3) & " seconds"
End If
If Cb.Msg = %WM_Command And Cb.Ctl = 200 And Cb.CtlMsg = %BN_Clicked Then
Local Source&, Dest&, ArrayLen&
For i = 0 To UBound(MyArray) : MyArray(i) = Rnd(1,1000) : Next i
iStart = GetTickCount
For i = 1 To 100000
' Source& = VarPTR(MyArray(0))
' Dest& = VarPTR(NewArray(0))
' ArrayLen& = (UBound(MyArray)+1) * SizeOf(MyArray(0)) 'byte length of zero-based array
' Poke$ Dest&, Peek$(Source&, ArrayLen&) 'copy block
Poke$ VarPtr(NewArray(0)), Peek$(VarPtr(MyArray(0)), (UBound(MyArray)+1) * SizeOf(MyArray(0))) 'copy block
Next i
iEnd = GetTickCount
MsgBox Format$((iEnd - iStart)/1000,3) & " seconds"
End If
If Cb.Msg = %WM_Command And Cb.Ctl = 300 And Cb.CtlMsg = %BN_Clicked Then
For i = 0 To UBound(MyArray) : MyArray(i) = Rnd(1,1000) : Next i
iStart = GetTickCount
For i = 1 To 100000
Mat NewArray() = MyArray()
Next i
iEnd = GetTickCount
MsgBox Format$((iEnd - iStart)/1000,3) & " seconds"
For i = 0 To UBound(NewArray) 'verify results
If NewArray(i) <> MyArray(i) Then ? "not equal" : Exit For
Next i
End If
If Cb.Msg = %WM_Command And Cb.Ctl = 400 And Cb.CtlMsg = %BN_Clicked Then
For i = 0 To UBound(MyArray) : MyArray(i) = Rnd(1,1000) : Next i
iStart = GetTickCount
For i = 1 To 100000
CopyMemory VarPtr(NewArray(0)), VarPtr(MyArray(0)), ArrayAttr(MyArray(),5) * ArrayAttr(MyArray(),4)
Next i
iEnd = GetTickCount
MsgBox Format$((iEnd - iStart)/1000,3) & " seconds"
For i = 0 To UBound(NewArray) 'verify results
If NewArray(i) <> MyArray(i) Then ? "not equal" : Exit For
Next i
End If
End Function
'gbs_00565
'Date: 03-10-2012
http://www.garybeene.com/sw/gbsnippets.htm