'=========================================================================== ' Subject: SWAP ARRAY DEMO Date: 10-17-95 (00:00) ' Author: Jamshid Khoshrangi Code: PB ' Origin: FidoNet POWER_BAS Echo Packet: PB.ABC '=========================================================================== $IF 0 SWAPARR.BAS SWAPARR.BAS SwapArray Demo Written by Jamshid Khoshrangi PURPOSE: Have you ever wanted to just do this with arrays: SWAP ArrayOne(), ArrayTwo() rather than this: FOR i = 1 TO UBOUND(ArrayOne) SWAP ArrayOne(i), ArrayTwo(i) NEXT i Well, this file demonstrates how to do it by swapping array descriptors. That's right -- just swap the descriptors in memory, and, well, the rest takes care of itself. From that point on, your arrays are swapped. I used my REDIM.PRESERVE code to demonstrate the speed gains that can be had by swapping just the descriptors, rather than every single data item. This code uses my ARRAYDESC32() function and Ethan Winer's SWAPMEM.ASM (turned in line). WARNINGS: Although the code checks the data types of the arrays, if you attempt to swap to user defined TYPEs arrays of different TYPEs but with the same overall length ... it chokes. In other words, the safeties I've added would generate run-time ERROR 10 (Duplicate definition) if you were to do this: SwapArray ArrayOne$(), ArrayTwo%(), 64 Or this: TYPE UserType1 A AS INTEGER END TYPE TYPE UserType2 A AS LONG END TYPE DIM ArrayOne() AS UserType1 DIM ArrayTwo() AS UserType2 SwapArray ArrayOne(), ArrayTwo(), 64 But NOT this: TYPE UserType1 A AS INTEGER ' these add up to B AS INTEGER ' an overall total of 4 bytes END TYPE TYPE UserType2 A AS LONG ' and this is four bytes END TYPE DIM ArrayOne() AS UserType1 DIM ArrayTwo() AS UserType2 SwapArray ArrayOne(), ArrayTwo(), 64 So look out when you swap arrays of user defined TYPEs. Also note that these routines use pedal-to-the-metal tricks to do what they do, so I cannot guarantee that they will run under anything other than what I tested them under: PB 3.2. If the array descriptor size ever changes, for instance, you must change the constant %ARRAY.DESC.SIZE to whatever it should be.... All else will crash. Explore and have fun with this.... Jamshid $ENDIF DECLARE FUNCTION ArrayInfo(BYVAL Code AS INTEGER, _ ArrayDescriptor AS ANY) AS LONG DEFINT A-Z %ARRAY.DESC.SIZE = 64 $IF 1 DIM DYNAMIC Test(1:10) AS STRING Test(10) = "Wow!" CLS MTIMER REDIM.PRESERVE Test(), 32000 PRINT "Using SwapArray: ", MTIMER ' Crunch it back down for the next test... REDIM.PRESERVE Test(), 10 MTIMER REDIM.PRESERVE.OLD Test(), 32000 PRINT "The old style: ", MTIMER END $ENDIF SUB SwapArray (_ BYVAL Var1 AS DWord,_ BYVAL Var2 AS DWord,_ BYVAL NumBytes AS Word) ' SWAPMEM.ASM was originally written by Ethan Winer and included ' with his great book on QuickBASIC.... ' First, we check that we are dealing with identical data types! IF ArrayInfo(4, BYVAL Var1) <> ArrayInfo(4, BYVAL Var2) THEN ERROR 10 ' This is the same error PB generates when you ' try to REDIM an array into a different data ' type than its original DIM ELSE ' If the arrays are of a user defined TYPE, we check to ' make sure that the elements are of the same length. This ' will catch most goof ups, but if type different types with ' identical overall lengths are swapped, this check fails to ' catch the error.... IF ArrayInfo(4, BYVAL Var1) = 12 THEN ' user defined TYPE IF ArrayInfo(2, BYVAL Var1) <> ArrayInfo(2, BYVAL Var2) THEN ERROR 10 END IF END IF END IF ! Lds SI,Var1 ;get the segmented address of the first variable ! Les DI,Var2 ;and for the second variable too ! Mov CX,NumBytes ;get the number of bytes to exchange ! Jcxz ExitLabel ;we can't swap zero bytes! ! Cld ;ensure Lodsb works forward DoSwap: ! Mov AL,ES:[DI] ;get a byte from the second variable ! Xchg AL,[SI] ;swap it with the first variable ! Stosb ;complete the swap and also increment DI ! Inc SI ;point to the next byte in the first variable ! Loop DoSwap ;continue until done ExitLabel: END SUB FUNCTION ARRAYDESC32 (ANY) AS DWORD DIM Desc AS DWORD ! mov ax, [bp+6] ! mov bx, [bp+8] ! mov Desc[0], ax ! mov Desc[2], bx FUNCTION = Desc END FUNCTION DEFINT A-Z %TRUE = -1 %FALSE = NOT %TRUE SUB REDIM.PRESERVE (InArray() AS STRING, NewMax AS INTEGER) ArrayStart = LBOUND (InArray) ArrayEnd = UBOUND(InArray) ' We'd better make it HUGE, just in case the original array was ' huge.... DIM HUGE OutArray(ArrayStart:NewMax) AS STRING SELECT CASE NewMax > ArrayEnd CASE %TRUE FOR i = ArrayStart TO ArrayEnd OutArray(i) = InArray(i) NEXT i CASE %FALSE FOR i = ArrayStart TO NewMax OutArray(i) = InArray(i) NEXT i END SELECT SwapArray ARRAYDESC32(InArray()),_ ARRAYDESC32(OutArray()),_ %ARRAY.DESC.SIZE END SUB SUB REDIM.PRESERVE.OLD (InArray() AS STRING, NewMax AS INTEGER) ArrayStart = LBOUND (InArray) ArrayEnd = UBOUND(InArray) ' We'd better make it HUGE, just in case the original array was ' huge.... DIM HUGE OutArray(ArrayStart:NewMax) AS STRING SELECT CASE NewMax > ArrayEnd CASE %TRUE FOR i = ArrayStart TO ArrayEnd OutArray(i) = InArray(i) NEXT i REDIM InArray(ArrayStart:NewMax) AS STRING FOR i = ArrayStart TO ArrayEnd InArray(i) = OutArray(i) NEXT i CASE FALSE FOR i = ArrayStart TO NewMax OutArray(i) = InArray(i) NEXT i REDIM InArray(ArrayStart:NewMax) AS STRING FOR i = ArrayStart TO NewMax InArray(i) = OutArray(i) NEXT i END SELECT END SUB