Private Const rRunner4 As Single = 0.0025 '0.002<<reverse-sorting-0.003-unsorted>>0.004
Private Const rRunner5 As Single = 0.0015 '0.001<<reverse-sorting-unsorted>>0.002
' Used for unsigned arithmetic
Private Const DW_MSB = &H80000000 ' DWord Most Significant Bit
Private Enum SAFEATURES
FADF_AUTO = &H1 ' Array is allocated on the stack
FADF_STATIC = &H2 ' Array is statically allocated
FADF_EMBEDDED = &H4 ' Array is embedded in a structure
FADF_FIXEDSIZE = &H10 ' Array may not be resized or reallocated
FADF_BSTR = &H100 ' An array of BSTRs
FADF_UNKNOWN = &H200 ' An array of IUnknown*
FADF_DISPATCH = &H400 ' An array of IDispatch*
FADF_VARIANT = &H800 ' An array of VARIANTs
FADF_RESERVED = &HFFFFF0E8 ' Bits reserved for future use
#If False Then
Dim FADF_AUTO, FADF_STATIC, FADF_EMBEDDED, FADF_FIXEDSIZE, FADF_BSTR, FADF_UNKNOWN, FADF_DISPATCH, FADF_VARIANT, FADF_RESERVED
#End If
End Enum
Private Const VT_BYREF = &H4000& ' Tests whether the InitedArray routine was passed a Variant that contains an array, rather than directly an array in the former case ptr already points to the SA structure. Thanks to Monte Hansen for this fix
Private Const FADF_NO_REDIM = FADF_AUTO Or FADF_FIXEDSIZE
Private Type SAFEARRAY
cDims As Integer ' Count of dimensions in this array
fFeatures As Integer ' Bitfield flags indicating attributes of a particular array
cbElements As Long ' Byte size of each element of the array
cLocks As Long ' Number of times the array has been locked without corresponding unlock
pvData As Long ' Pointer to the start of the array data (use only if cLocks > 0)
cElements As Long ' Count of elements in this dimension
lLBound As Long ' The lower-bounding index of this dimension
lUBound As Long ' The upper-bounding index of this dimension
End Type
Private StringPtrs_Header As SAFEARRAY
Private StringPtrs() As Long
Private ssLb() As Long, ssUb() As Long, ssMax As Long ' Avalanche pending boundary stacks
Private psLb() As Long, psUb() As Long, psMax As Long ' Stable presorter boundary stacks
Private lA_1() As Long, lA_2() As Long, ssBuf As Long ' Stable quicksort working buffers
Private twLb() As Long, twUb() As Long, twMax As Long ' Twister runner stacks
Private twBuf() As Long, twBufMax As Long ' Twister copymemory buffer
If Not (StrComp(sA(run - n1), item, mMethod) = eComp) Then Exit Do
run = run - n1
Loop: cast = lbA + inter1 - run
If cast Then
CopyMemByV lpL_1, Sum(lpS, run * n4), cast * n4 ' Grab items that stayed below current that should also be above items that have moved down below current
CopyMemByV Sum(lpS, run * n4), Sum(lpS, (lbA + inter1) * n4), (ptr1 - inter1) * n4 ' Move down items
CopyMemByV Sum(lpS, (lbA + ptr1 - cast - n1) * n4), lpL_1, cast * n4 ' Re-assign items into position immediately below current item
End If
End If ' 1 2 1r item 4r 3 4
If (inter2) And (ptr2 - inter2 < n50K) Then
base = lbA + ptr1 + n1
CopyMemByR ByVal lpStr, StringPtrs(base), n4
pvt = lbA + ptr1 + inter2
opt = pvt + ((ptr2 - inter2) \ n2)
run = pvt
Do While run < opt ' Runner do loop
If Not (StrComp(sA(run + n1), item, mMethod) = eComp) Then Exit Do
run = run + n1
Loop: cast = run - pvt
If cast Then
CopyMemByV lpL_1, Sum(lpS, (pvt + n1) * n4), cast * n4 ' Grab items that stayed above current that should also be below items that have moved up above current
CopyMemByV Sum(lpS, (base + cast) * n4), Sum(lpS, base * n4), inter2 * n4 ' Move up items
CopyMemByV Sum(lpS, base * n4), lpL_1, cast * n4 ' Re-assign items into position immediately above current item
End If: End If: End If
ElseIf (inter2 = n0) Then
If (inter1 = ptr1) Then ' Refresh
' Delegate to built-in Insert/Binary hybrid on ideal data state
If Not (StrComp(sA(run - n1), item, mMethod) = eComp) Then Exit Do
run = run - n1
Loop: cast = lbA + inter1 - run
If cast Then
CopyMemByV lpL_1, Sum(lpS, run * n4), cast * n4 ' Grab items that stayed below current that should also be above items that have moved down below current
CopyMemByV Sum(lpS, run * n4), Sum(lpS, (lbA + inter1) * n4), (ptr1 - inter1) * n4 ' Move down items
CopyMemByV Sum(lpS, (lbA + ptr1 - cast - n1) * n4), lpL_1, cast * n4 ' Re-assign items into position immediately below current item
End If
End If ' 1 2 1r item 4r 3 4
If (inter2) And (ptr2 - inter2 < n50K) Then
base = lbA + ptr1 + n1
CopyMemByR ByVal lpStr, StringPtrs(base), n4
pvt = lbA + ptr1 + inter2
opt = pvt + ((ptr2 - inter2) \ n2)
run = pvt
Do While run < opt ' Runner do loop
If Not (StrComp(sA(run + n1), item, mMethod) = eComp) Then Exit Do
run = run + n1
Loop: cast = run - pvt
If cast Then
CopyMemByV lpL_1, Sum(lpS, (pvt + n1) * n4), cast * n4 ' Grab items that stayed above current that should also be below items that have moved up above current
CopyMemByV Sum(lpS, (base + cast) * n4), Sum(lpS, base * n4), inter2 * n4 ' Move up items
CopyMemByV Sum(lpS, base * n4), lpL_1, cast * n4 ' Re-assign items into position immediately above current item
End If: End If: End If: End If
If (ptr1 > n1) Then
If (ptr2 > n1) Then cnt = cnt + n1: ssLb(cnt) = lbA + ptr1 + n1: ssUb(cnt) = ubA
If Not (StrComp(sA(idxA(run - n1)), item, mMethod) = eComp) Then Exit Do
run = run - n1
Loop: cast = lbA + inter1 - run
If cast Then
CopyMemByV lpL_1, Sum(lpI, run * n4), cast * n4 ' Grab items that stayed below current that should also be above items that have moved down below current
CopyMemByV Sum(lpI, run * n4), Sum(lpI, (lbA + inter1) * n4), (ptr1 - inter1) * n4 ' Move down items
CopyMemByV Sum(lpI, (lbA + ptr1 - cast - n1) * n4), lpL_1, cast * n4 ' Re-assign items into position immediately below current item
End If
End If ' 1 2 1r item 4r 3 4
If (inter2) And (ptr2 - inter2 < n50K) Then
base = lbA + ptr1 + n1
CopyMemByV lpStr, Sum(lpS, idxA(base) * n4), n4
pvt = lbA + ptr1 + inter2
opt = pvt + ((ptr2 - inter2) \ n2)
run = pvt
Do While run < opt ' Runner do loop
If Not (StrComp(sA(idxA(run + n1)), item, mMethod) = eComp) Then Exit Do
run = run + n1
Loop: cast = run - pvt
If cast Then
CopyMemByV lpL_1, Sum(lpI, (pvt + n1) * n4), cast * n4 ' Grab items that stayed above current that should also be below items that have moved up above current
CopyMemByV Sum(lpI, (base + cast) * n4), Sum(lpI, base * n4), inter2 * n4 ' Move up items
CopyMemByV Sum(lpI, base * n4), lpL_1, cast * n4 ' Re-assign items into position immediately above current item
End If: End If: End If
ElseIf (inter2 = n0) Then
If (inter1 = ptr1) Then ' Refresh
' Delegate to built-in Insert/Binary hybrid on ideal data state
If Not (StrComp(sA(idxA(run - n1)), item, mMethod) = eComp) Then Exit Do
run = run - n1
Loop: cast = lbA + inter1 - run
If cast Then
CopyMemByV lpL_1, Sum(lpI, run * n4), cast * n4 ' Grab items that stayed below current that should also be above items that have moved down below current
CopyMemByV Sum(lpI, run * n4), Sum(lpI, (lbA + inter1) * n4), (ptr1 - inter1) * n4 ' Move down items
CopyMemByV Sum(lpI, (lbA + ptr1 - cast - n1) * n4), lpL_1, cast * n4 ' Re-assign items into position immediately below current item
End If
End If ' 1 2 1r item 4r 3 4
If (inter2) And (ptr2 - inter2 < n50K) Then
base = lbA + ptr1 + n1
CopyMemByV lpStr, Sum(lpS, idxA(base) * n4), n4
pvt = lbA + ptr1 + inter2
opt = pvt + ((ptr2 - inter2) \ n2)
run = pvt
Do While run < opt ' Runner do loop
If Not (StrComp(sA(idxA(run + n1)), item, mMethod) = eComp) Then Exit Do
run = run + n1
Loop: cast = run - pvt
If cast Then
CopyMemByV lpL_1, Sum(lpI, (pvt + n1) * n4), cast * n4 ' Grab items that stayed above current that should also be below items that have moved up above current
CopyMemByV Sum(lpI, (base + cast) * n4), Sum(lpI, base * n4), inter2 * n4 ' Move up items
CopyMemByV Sum(lpI, base * n4), lpL_1, cast * n4 ' Re-assign items into position immediately above current item
End If: End If: End If: End If
If (ptr1 > n1) Then
If (ptr2 > n1) Then cnt = cnt + n1: ssLb(cnt) = lbA + ptr1 + n1: ssUb(cnt) = ubA
' This function returns a pointer to the SAFEARRAY header of
' any Visual Basic array, including a Visual Basic string array.
' Substitutes both ArrPtr and StrArrPtr.
' This function will work with vb5 or vb6 without modification.
Function ArrayPtr(Arr) As Long
Dim iDataType As Integer
On Error GoTo UnInit
CopyMemByR iDataType, Arr, n2 ' get the real VarType of the argument, this is similar to VarType(), but returns also the VT_BYREF bit
If (iDataType And vbArray) = vbArray Then ' if a valid array was passed
CopyMemByR ArrayPtr, ByVal Sum(VarPtr(Arr), n8), n4 ' get the address of the SAFEARRAY descriptor stored in the second half of the Variant parameter that has received the array. Thanks to Francesco Balena.
End If
UnInit:
End Function
' + Validate Index Array +++++++++++++++++++++++++++++++++++++
' This will prepare the passed index array if it is not already.
' This sub-routine determines if the index array passed is either:
' [A] uninitialized or Erased
' initialized to invalid boundaries
' initialized to valid boundaries but not prepared
' [B] initialized to extended boundaries and not fully prepared
' [C] prepared for the sort process by the For loop
' has been modified by a previous sort process
' If the condition is determined to be [A] then it is prepared by
' executing the For loop code, if the condition is determined to
' be [B] then it is prepared only from the old ub to the new ub,
' otherwise if [C] nothing is done
' This will Threparfreptm th idxA(l' othf the SAFEARRAY descriptor stox ar
' This su nd n ar
' o + ptr1 + inter2down belotrb<ku thoy headuntmsub- ElseIf (ptrDrt Do ' It ' Wa Copy Rut Valida' Iries but not prepared
' uthis of current ' It ' Wa CopySid ao + pt Rss of the SAFEARRAY descriptor stored in the second half of thuni(d n ar
Inited in the secr ltor st1) * n4), lpL_1A(idx) ' 1
ptr1 = ptr1 + n1
End If
Next
inter1 = ptr1: inter2 = ptr2
For idx = pvt + n1 To ubA
If (StrComp(item, sA(idxA(idx)), mMethod) = eComp) Then ' (idx < item)
lA_ sA(iUnIni lA_ sA(iUf. pvt)
n1
End If
Next
inter1 = ptr1: inter2 = ptr2
For idx = pvt + n1 To ubA
If (StrComp(item, sA(idxA(idx)), mMethod) = eComp) Then ' (idx < item)
lA_ sA(iUnIni lA_ sA(iUf. pvt)
,f
=e a If (StrComp(itemP If (StrComp(i+ n1r = -1&
Equal = 0&
mezz Or rst * n4 C + iurrComp(i+ n1o If (StrComp(il'rot (mbAIf hat stayt stayt stayt stayt statrComp(Re-assign items into p thun ' IzIcl tem
find = walk izer1 lz0K) Th it trCo0 tem, sA(idxA(dariesate m0 tem =en1) * n4), lpL_1, cast
e IfdxA(t* nameter tha(Stetee a(dariee CopyMemByV a aassign items.=cast
e IfdxA(t* n r Gourrenttttt, lpems i g, lA_2unction
' + (t*yt st ptr1 = ptr1 + nEWnction
ign items into p thun ' IzIcl tem
find = walk
lourrentttiS pvt)
n1
End If
Next
inter1 = ptr1: inter2 = ptr2
For idx = pvt + n1 uhtk
d
xd 2) Thc++++ IzI 'myffffttw Au2ttttt, find = walk
ign items '*bc( Then'CpV lpl Nn iteitem, s'*y ' b, ng idxA(id in them, s'*y idxm =en13 4
A_2unter1 = ptr1: ia Next
' + (t*yt slS pvn1) Then cnt = cnt + n17a) = eCe
louF bc( s ' 1 2 item 3 4
e,o iteitem, sn> This will p ize esys ip1 2 itemtrCompre,o iteitem, sn> This will p TuIt
hen ter) If (StrComp(item, sA(idxA(urn
zhis will
' ptr1: ia Nexrrent itemn1) T)t p atem, sype As ,em, ATiwMax, esys ip1tn cnt = cnt + nproces opt =o r do opt =o r do opt =o r do opt =o r do opt =o r do opt =o r do opt =o r do opt =o r do opt =o F bG slS A_2unp
' has been modified by a previous sort process
' If the conditDhas been t =oo inter1 = ptr1: interMt = cnt + n17a) = eCe
vo ' Rfo"tion
ptterMr2o bG slStionhen bGSB rktdx = pvt + no + n1 T arrl=Dteue be [ABEqual- n1Arm n16 bG slStionhen b uB sMemByV lbG pt =o Rut copyMr do opt =o r do opt =o r do opt =o n1A ndit, s'E slpems ule
Envious s-_1, .t,eCe
: interMt gex A r do VD End If
d Io VD: interMt gex A8 t gex a
x = pvt + no + n1 T arrl=Dteue be [ABEqusG slSttdx = pvt + no + n1 T arrl=Dteue be [ABEqual- n1Arm n16 bG slStionhen b uB sMemByV lbG pt =o Rut Sube [E slSahen_hen ized dinteb r do h dinteb r do h dinteb r do h dio be [ n1 sMax, opt =o lt" ay if it is r bG pt =o Rut un - n1A ndit, s'E slpems ule
Envious s-_1, .t,eCe
: interMt gex A r do VD 4RAY d Sube [E slSahen d r t 4RAY, n4 ' Grab current value into item
find = walk . . ... . b paredt gexb paredt mByV l If on
j If rrentttiS , s 'pie
ew. ... . . ... aredtd End If)c [ n1 e bG slStl opt =o d If
o"l ip1 2 itemtrCompre,o iteo btLlpemD izer1bre1I, (pvterzer1ben o r do opt =o r do opt =o r do opt =o r do opt =o F ò11 T nt + n1: ssLb(cnt) = lbAoD opt =w opt =o ++ IzI 'my find = walk . . ... . , lue inti has been modisax, o F bG slS A_2unp
' has been modified by a previous sort process
teb into nC nlpemfa ab intdt i7 E!ameterA a po F òw otTe"Rn ' Grab currenles
Z opt =o r do . erA a (lpIey1di run = run + 1
Loop: cast = (run - walk)
;e lj n ' Runner do loop
, eiiiiiic bo Rutgn btLl sMem Enedtd End If)c [ n1 e bG slStl opt =o d If
o"l ip1 2 itemtrCompre,o iteo btLlpemD izeeI d IdtbG slStllStl opt =o c ar' rei l runAfeg r do opt =o r do VD 4RAY d Sube [Edit, s'E slp n4),ti htebent value into it rdt i7Rf> tw + inter1 - r- pvt
e ' Defaul v3pemfaax, o F bG slS oD opt =w opt =o ++ d Idd lS y findeT. ... .t abo Rut pt =w opt =o ++ d IdbindeT. .. find ==o ++ d Idbin'lv fint =w bG s e iteo f e suni: int-,Nexube [Ee below current
xlue into iiteoP-InAY d f e ++ into iRutgit, s S f ...A ndit, s'E slpems ule
Envious s-_1, .t,eCe
: interMt gex A r do VD 4RA
oooooooooooooooor"Rn ' GrabbG b If r dpt =o ++ )r dpt , 1 opt =o r do opt =o r xlue into iiteo find = walk
l bG sTi d Idtgn n )r tLl rdt iinter++ d IdbindeT. .. bNexu bs m0 tem =en1) * n4), lpL_1, c *yt o Bal midd = (base + ceil) \ n2 ' iiteo find = walk
l em =en1intoe f e ++ iiteo eile, s'*y21 slS I'CS' Defaul++ d Idbind = pvt +
' + Arraexu bunA,1, c unne e ' Set base t'*y21 CopyMemByVUUUUUUUfet base t'*y21 a(ito iiteomiddeT.nlpI,' f tLlUp t eT. .. find ==o it bat =o 1eComp) Then ' (idx < iteen c b If rerMr2oA8 t t If rerMriDatMemByV a t r- pvt
e e=en1intoe f et
e e=en1intoe f et
e e=en ' Defaul rrlscint' reo =en1intoe c b 'ae e=en d)unner Ifen1iu n1 lm =en1int ind = walk