﻿B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Class
Version=9.801
@EndOfDesignText@
Sub Class_Globals
	Type tSort(strValue As String, _
			   iIndex As Int)
End Sub

'Initializes the object. You can add parameters to this method if needed.
'Note that this needs running even although there is no code in this Sub!
'------------------------------------------------------------------------
Public Sub Initialize
	
End Sub

'Will produce 1D int array with number of dimensions in first element and then lengths of all dimensions.
Sub GetArrayInfo(oArray As Object) As Int()
	
	Dim i As Int
	Dim r As Reflector
	Dim dims() As Int
	
	r.Target = oArray
	dims = r.TargetRank

	Dim arrInt(dims.Length + 1) As Int
	arrInt(0) = dims.Length
	
	For i = 0 To dims.Length -1
		arrInt(i + 1) = dims(i)
	Next
	
	Return arrInt
	
End Sub

Sub Check1DIntAllSame(arrInt() As Int, iStart As Int, iEnd As Int) As Boolean
	
	Dim i As Int
	Dim iVal As Int
	
	If arrInt.Length = 1 Then
		Return True
	End If
	
	If iStart = -1 Then
		iStart = 1
	End If
	
	If iEnd = -1 Then
		iEnd = arrInt.Length - 1
	End If
	
	iVal = arrInt(0)
	
	For i = iStart To iEnd
		If arrInt(i) <> iVal Then
			Return False
		End If
	Next
	
	Return True
	
End Sub

Sub Check1DLongAllSame(arrLong() As Long, iStart As Int, iEnd As Int) As Boolean
	
	Dim i As Int
	Dim lVal As Long
	
	If arrLong.Length = 1 Then
		Return True
	End If
	
	If iStart = -1 Then
		iStart = 1
	End If
	
	If iEnd = -1 Then
		iEnd = arrLong.Length - 1
	End If
	
	lVal = arrLong(0)
	
	For i = iStart To iEnd
		If arrLong(i) <> lVal Then
			Return False
		End If
	Next
	
	Return True
	
End Sub

Sub Check1DDoubleAllSame(arrDouble() As Double, iStart As Int, iEnd As Int) As Boolean
	
	Dim i As Int
	Dim dVal As Double
	
	If arrDouble.Length = 1 Then
		Return True
	End If
	
	If iStart = -1 Then
		iStart = 1
	End If
	
	If iEnd = -1 Then
		iEnd = arrDouble.Length - 1
	End If
	
	dVal = arrDouble(0)
	
	For i = iStart To iEnd
		If arrDouble(i) <> dVal Then
			Return False
		End If
	Next
	
	Return True
	
End Sub

Sub Check1DStringAllSame(arrstring() As String, bCaseInsensitive As Boolean, iStart As Int, iEnd As Int) As Boolean
	
	Dim i As Int
	Dim str As String
	
	If arrstring.Length = 1 Then
		Return True
	End If
	
	If iStart = -1 Then
		iStart = 1
	End If
	
	If iEnd = -1 Then
		iEnd = arrstring.Length - 1
	End If
	
	If bCaseInsensitive Then
		str = arrstring(0).ToLowerCase
		For i = iStart To iEnd
			If arrstring(i).ToLowerCase.CompareTo(str) <> 0 Then
				Return False
			End If
		Next
	Else
		str = arrstring(0)
		For i = iStart To iEnd
			If arrstring(i).CompareTo(str) <> 0 Then
				Return False
			End If
		Next
	End If
	
	Return True
	
End Sub

Sub Check1DIntListAllSame(oList As List, iStart As Int, iEnd As Int) As Boolean  'ignore warning
	
	Dim i As Int
	Dim iVal As Int
	
	If oList.size = 1 Then
		Return True
	End If
	
	If iStart = -1 Then
		iStart = 1
	End If
	
	If iEnd = -1 Then
		iEnd = oList.Size - 1
	End If
	
	iVal = oList.Get(0)
	
	For i = iStart To iEnd
		If iVal <> oList.Get(i) Then
			Return False
		End If
	Next
	
	Return True
	
End Sub

Sub SortOMIntListIDX(oList As List, bAscending As Boolean, iStart As Int, iEnd As Int) As Int()

	Dim i As Long
	Dim c As Long
	Dim n As Long
	Dim B4XOM As B4XOrderedMap
	Dim arrInt(oList.Size) As Int
	
	If iStart = -1 Then
		iStart = 0
	End If
	
	If iEnd = -1 Then
		iEnd = oList.Size - 1
	End If
	
	'we need the int array as the list items are considered
	'Double and that is causing problems with the B4XOrderedMap
	'----------------------------------------------------------
	For i = iStart To iEnd
		arrInt(i) = oList.Get(i)
	Next
	
	If Check1DIntAllSame(arrInt, iStart, iEnd) Then
		Dim arrIndex2(1) As Int
		arrIndex2(0) = -1
		Return arrIndex2
	End If
		
	B4XOM.Initialize
		
	For i = iStart To iEnd
		Dim lstIndexes As List
		If B4XOM.ContainsKey(arrInt(i)) Then
			lstIndexes = B4XOM.Get(arrInt(i))
		Else
			lstIndexes.Initialize
		End If
		lstIndexes.Add(i)
		B4XOM.Put(arrInt(i), lstIndexes)
	Next
	
	B4XOM.Keys.Sort(bAscending)
	
	Dim arrIndex((iEnd - iStart) + 1) As Int
	
	For Each oValue As Object In B4XOM.Values
		lstIndexes = oValue
		For c = 0 To lstIndexes.Size - 1
			arrIndex(n) = lstIndexes.Get(c)
			n = n + 1
		Next
	Next
	
	Return arrIndex
		
End Sub

Sub SortOMStringListIDX(oList As List, bAscending As Boolean, bCaseInsensitive As Boolean, iStart As Int, iEnd As Int, bCheckAllSame As Boolean) As Int()

	Dim i As Long
	Dim c As Long
	Dim n As Long
	Dim B4XOM As B4XOrderedMap
	Dim arrString(oList.Size) As String
	
	If iStart = -1 Then
		iStart = 0
	End If
	
	If iEnd = -1 Then
		iEnd = oList.Size - 1
	End If

	For i = iStart To iEnd
		arrString(i) = oList.Get(i)
	Next
	
	If bCaseInsensitive Then
		For i = iStart To iEnd
			arrString(i) = arrString(i).ToLowerCase
		Next
	End If
	
	If bCheckAllSame Then
		If Check1DStringAllSame(arrString, False, iStart, iEnd) Then
			Dim arrIndex2(1) As Int
			arrIndex2(0) = -1 'telling the calling Sub that all items were same, so no need for any sort
			Return arrIndex2
		End If
	End If
		
	B4XOM.Initialize

	For i = iStart To iEnd
		Dim lstIndexes As List
		If B4XOM.ContainsKey(arrString(i)) Then
			lstIndexes = B4XOM.Get(arrString(i))
		Else
			lstIndexes.Initialize
		End If
		lstIndexes.Add(i)
		B4XOM.Put(arrString(i), lstIndexes)
	Next
	
	B4XOM.Keys.Sort(bAscending)
	
	Dim arrIndex((iEnd - iStart) + 1) As Int
	
	For Each oValue As Object In B4XOM.Values
		lstIndexes = oValue
		For c = 0 To lstIndexes.Size - 1
			arrIndex(n) = lstIndexes.Get(c)
			n = n + 1
		Next
	Next
	
	Return arrIndex
		
End Sub

Sub SortOMIntIDX(arrInt() As Int, bAscending As Boolean, iStart As Int, iEnd As Int) As Int()

	Dim i As Long
	Dim c As Long
	Dim n As Long
	Dim B4XOM As B4XOrderedMap
	
	If Check1DIntAllSame(arrInt, iStart, iEnd) Then
		Dim arrIndex2(1) As Int
		arrIndex2(0) = -1
		Return arrIndex2
	End If
		
	B4XOM.Initialize
	
	If iStart = -1 Then
		iStart = 0
	End If
	
	If iEnd = -1 Then
		iEnd = arrInt.Length - 1
	End If
		
	For i = iStart To iEnd
		Dim lstIndexes As List
		If B4XOM.ContainsKey(arrInt(i)) Then
			lstIndexes = B4XOM.Get(arrInt(i))
		Else
			lstIndexes.Initialize
		End If
		lstIndexes.Add(i)
		B4XOM.Put(arrInt(i), lstIndexes)
	Next
	
	B4XOM.Keys.Sort(bAscending)
	
	Dim arrIndex((iEnd - iStart) + 1) As Int
	
	For Each oValue As Object In B4XOM.Values
		lstIndexes = oValue
		For c = 0 To lstIndexes.Size - 1
			arrIndex(n) = lstIndexes.Get(c)
			n = n + 1
		Next
	Next
	
	Return arrIndex
		
End Sub

Sub SortOMLongIDX(arrLong() As Long, bAscending As Boolean, iStart As Int, iEnd As Int) As Int()

	Dim i As Long
	Dim c As Long
	Dim n As Long
	Dim B4XOM As B4XOrderedMap
	
	If Check1DLongAllSame(arrLong, iStart, iEnd) Then
		Dim arrIndex2(1) As Int
		arrIndex2(0) = -1
		Return arrIndex2
	End If
		
	B4XOM.Initialize
	
	If iStart = -1 Then
		iStart = 0
	End If
	
	If iEnd = -1 Then
		iEnd = arrLong.Length - 1
	End If
		
	For i = iStart To iEnd
		Dim lstIndexes As List
		If B4XOM.ContainsKey(arrLong(i)) Then
			lstIndexes = B4XOM.Get(arrLong(i))
		Else
			lstIndexes.Initialize
		End If
		lstIndexes.Add(i)
		B4XOM.Put(arrLong(i), lstIndexes)
	Next
	
	B4XOM.Keys.Sort(bAscending)
	
	Dim arrIndex((iEnd - iStart) + 1) As Int
	
	For Each oValue As Object In B4XOM.Values
		lstIndexes = oValue
		For c = 0 To lstIndexes.Size - 1
			arrIndex(n) = lstIndexes.Get(c)
			n = n + 1
		Next
	Next
	
	Return arrIndex
		
End Sub

Sub SortOMLongIDX2(arrLong() As Long, arrIndex() As Int, bAscending As Boolean, iStart As Int, iEnd As Int) As Int()

	Dim i As Long
	Dim c As Long
	Dim n As Long
	Dim B4XOM As B4XOrderedMap
	
	If Check1DLongAllSame(arrLong, iStart, iEnd) Then
		Dim arrIndex2(1) As Int
		arrIndex2(0) = -1
		Return arrIndex2
	End If
		
	B4XOM.Initialize
	
	If iStart = -1 Then
		iStart = 0
	End If
	
	If iEnd = -1 Then
		iEnd = arrLong.Length - 1
	End If
		
	For i = iStart To iEnd
		Dim lstIndexes As List
		If B4XOM.ContainsKey(arrLong(arrIndex(i))) Then
			lstIndexes = B4XOM.Get(arrLong(arrIndex(i)))
		Else
			lstIndexes.Initialize
		End If
		lstIndexes.Add(arrIndex(i))
		B4XOM.Put(arrLong(arrIndex(i)), lstIndexes)
	Next
	
	B4XOM.Keys.Sort(bAscending)
	
	Dim arrIndex2((iEnd - iStart) + 1) As Int
	
	For Each oValue As Object In B4XOM.Values
		lstIndexes = oValue
		For c = 0 To lstIndexes.Size - 1
			arrIndex2(n) = lstIndexes.Get(c)
			n = n + 1
		Next
	Next
	
	Return arrIndex2
		
End Sub

Sub SortOMDoubleIDX(arrDouble() As Double, bAscending As Boolean, iStart As Int, iEnd As Int) As Int()

	Dim i As Long
	Dim c As Long
	Dim n As Long
	Dim B4XOM As B4XOrderedMap
	
	If Check1DDoubleAllSame(arrDouble, iStart, iEnd) Then
		Dim arrIndex2(1) As Int
		arrIndex2(0) = -1
		Return arrIndex2
	End If
		
	B4XOM.Initialize
	
	If iStart = -1 Then
		iStart = 0
	End If
	
	If iEnd = -1 Then
		iEnd = arrDouble.Length - 1
	End If
		
	For i = iStart To iEnd
		Dim lstIndexes As List
		If B4XOM.ContainsKey(arrDouble(i)) Then
			lstIndexes = B4XOM.Get(arrDouble(i))
		Else
			lstIndexes.Initialize
		End If
		lstIndexes.Add(i)
		B4XOM.Put(arrDouble(i), lstIndexes)
	Next
	
	B4XOM.Keys.Sort(bAscending)
	
	Dim arrIndex((iEnd - iStart) + 1) As Int
	
	For Each oValue As Object In B4XOM.Values
		lstIndexes = oValue
		For c = 0 To lstIndexes.Size - 1
			arrIndex(n) = lstIndexes.Get(c)
			n = n + 1
		Next
	Next

	Return arrIndex
		
End Sub

Sub SortOMDoubleIDX2(arrDouble() As Double, arrIndex() As Int, bAscending As Boolean, iStart As Int, iEnd As Int) As Int()

	Dim i As Long
	Dim c As Long
	Dim n As Long
	Dim B4XOM As B4XOrderedMap
	
	If Check1DDoubleAllSame(arrDouble, iStart, iEnd) Then
		Dim arrIndex2(1) As Int
		arrIndex2(0) = -1
		Return arrIndex2
	End If
		
	B4XOM.Initialize
	
	If iStart = -1 Then
		iStart = 0
	End If
	
	If iEnd = -1 Then
		iEnd = arrDouble.Length - 1
	End If
		
	For i = iStart To iEnd
		Dim lstIndexes As List
		If B4XOM.ContainsKey(arrDouble(arrIndex(i))) Then
			lstIndexes = B4XOM.Get(arrDouble(arrIndex(i)))
		Else
			lstIndexes.Initialize
		End If
		lstIndexes.Add(arrIndex(i))
		B4XOM.Put(arrDouble(arrIndex(i)), lstIndexes)
	Next
	
	B4XOM.Keys.Sort(bAscending)
	
	Dim arrIndex2((iEnd - iStart) + 1) As Int
	
	For Each oValue As Object In B4XOM.Values
		lstIndexes = oValue
		For c = 0 To lstIndexes.Size - 1
			arrIndex2(n) = lstIndexes.Get(c)
			n = n + 1
		Next
	Next

	Return arrIndex2
		
End Sub

Sub SortOMStringIDX(arrString() As String, bAscending As Boolean, bCaseInsensitive As Boolean, iStart As Int, iEnd As Int) As Int()

	Dim i As Long
	Dim c As Long
	Dim n As Long
	Dim B4XOM As B4XOrderedMap
	
	If Check1DStringAllSame(arrString, bCaseInsensitive, iStart, iEnd) Then
		Dim arrIndex2(1) As Int
		arrIndex2(0) = -1
		Return arrIndex2
	End If
		
	B4XOM.Initialize
	
	If iStart = -1 Then
		iStart = 0
	End If
	
	If iEnd = -1 Then
		iEnd = arrString.Length - 1
	End If
		
	For i = iStart To iEnd
		Dim lstIndexes As List
		If B4XOM.ContainsKey(arrString(i)) Then
			lstIndexes = B4XOM.Get(arrString(i))
		Else
			lstIndexes.Initialize
		End If
		lstIndexes.Add(i)
		B4XOM.Put(arrString(i), lstIndexes)
	Next
	
	If bCaseInsensitive Then
		B4XOM.Keys.SortCaseInsensitive(bAscending)
	Else
		B4XOM.Keys.Sort(bAscending)
	End If
	
	Dim arrIndex((iEnd - iStart) + 1) As Int
	
	For Each oValue As Object In B4XOM.Values
		lstIndexes = oValue
		For c = 0 To lstIndexes.Size - 1
			arrIndex(n) = lstIndexes.Get(c)
			n = n + 1
		Next
	Next
	
	Return arrIndex
		
End Sub

Sub SortOMStringIDX2(arrString() As String, arrIndex() As Int, bAscending As Boolean, bCaseInsensitive As Boolean, iStart As Int, iEnd As Int) As Int()

	Dim i As Long
	Dim c As Long
	Dim n As Long
	Dim B4XOM As B4XOrderedMap
	
	If Check1DStringAllSame(arrString, bCaseInsensitive, iStart, iEnd) Then
		Dim arrIndex2(1) As Int
		arrIndex2(0) = -1
		Return arrIndex2
	End If
		
	B4XOM.Initialize
	
	If iStart = -1 Then
		iStart = 0
	End If
	
	If iEnd = -1 Then
		iEnd = arrString.Length - 1
	End If
		
	For i = iStart To iEnd
		Dim lstIndexes As List
		If B4XOM.ContainsKey(arrString(arrIndex(i))) Then
			lstIndexes = B4XOM.Get(arrString(arrIndex(i)))
		Else
			lstIndexes.Initialize
		End If
		lstIndexes.Add(arrIndex(i))
		B4XOM.Put(arrString(arrIndex(i)), lstIndexes)
	Next
	
	If bCaseInsensitive Then
		B4XOM.Keys.SortCaseInsensitive(bAscending)
	Else
		B4XOM.Keys.Sort(bAscending)
	End If
	
	Dim arrIndex2((iEnd - iStart) + 1) As Int
	
	For Each oValue As Object In B4XOM.Values
		lstIndexes = oValue
		For c = 0 To lstIndexes.Size - 1
			arrIndex2(n) = lstIndexes.Get(c)
			n = n + 1
		Next
	Next
	
	Return arrIndex2
		
End Sub

Sub TimSortInt_IDX(arrInt() As Int) As Int()
	
	Dim i As Int
	Dim n As Int
	Dim lSize As Int
	Dim lBegin As Int
	Dim lEnd As Int
	Dim lMid As Int
	Dim iConstRun As Int = 32
	
	n = arrInt.Length
	
	If Check1DIntAllSame(arrInt, -1, -1) Then
		Dim arrIndex(1) As Int
		arrIndex(0) = -1
		Return arrIndex
	Else
		Dim arrIndex(arrInt.Length) As Int
		For i = 0 To arrInt.Length - 1
			arrIndex(i) = i
		Next
	End If
	
	For i = 0 To n - 1 Step iConstRun
		TimInsertionInt_IDX(arrInt, arrIndex, i, Min(i + iConstRun - 1, n - 1))   '<---- HERE, replace '31' by 'iConstRun-1'
	Next
	
	lSize = iConstRun
	
	Do While lSize <= n-1
		For lBegin = 0 To n - 1 Step 2 * lSize      '<-- should be done like this
			lEnd = Min(lBegin + 2 * lSize - 1, n - 1)
			lMid = lBegin + lSize - 1
			If lMid < lEnd Then                     '<-- Add this condition to prevent crashes when size is not a multiple of run.
				TimMergeInt_IDX(arrInt, arrIndex, lBegin, lMid, lEnd)
			End If
		Next
		lSize = lSize * 2
	Loop
	
	Return arrIndex
	
End Sub

Sub TimSortDouble_IDX(arrDouble() As Double) As Int()
	
	Dim i As Int
	Dim n As Int
	Dim lSize As Int
	Dim lBegin As Int
	Dim lEnd As Int
	Dim lMid As Int
	Dim iConstRun As Int = 32
	
	n = arrDouble.Length
	
	If Check1DDoubleAllSame(arrDouble, -1, -1) Then
		Dim arrIndex(1) As Int
		arrIndex(0) = -1
		Return arrIndex
	Else
		Dim arrIndex(arrDouble.Length) As Int
	End If
	
	For i = 0 To arrDouble.Length - 1
		arrIndex(i) = i
	Next
	
	For i = 0 To n - 1 Step iConstRun
		TimInsertionDouble_IDX(arrDouble, arrIndex, i, Min(i + iConstRun - 1, n - 1))   '<---- HERE, replace '31' by 'iConstRun-1'
	Next
	
	lSize = iConstRun
	
	Do While lSize <= n-1
		For lBegin = 0 To n - 1 Step 2 * lSize      '<-- should be done like this
			lEnd = Min(lBegin + 2 * lSize - 1, n - 1)
			lMid = lBegin + lSize - 1
			If lMid < lEnd Then                     '<-- Add this condition to prevent crashes when size is not a multiple of run.
				TimMergeDouble_IDX(arrDouble, arrIndex, lBegin, lMid, lEnd)
			End If
		Next
		lSize = lSize * 2
	Loop
	
	Return arrIndex
	
End Sub

Sub TimSortLong_IDX(arrLong() As Long) As Int()
	
	Dim i As Int
	Dim n As Int
	Dim lSize As Int
	Dim lBegin As Int
	Dim lEnd As Int
	Dim lMid As Int
	Dim iConstRun As Int = 32
	
	n = arrLong.Length
	
	If Check1DLongAllSame(arrLong, -1, -1) Then
		Dim arrIndex(1) As Int
		arrIndex(0) = -1
		Return arrIndex
	Else
		Dim arrIndex(arrLong.Length) As Int
	End If
	
	For i = 0 To n - 1
		arrIndex(i) = i
	Next
	
	For i = 0 To n - 1 Step iConstRun
		TimInsertionLong_IDX(arrLong, arrIndex, i, Min(i + iConstRun - 1, n - 1))   '<---- HERE, replace '31' by 'iConstRun-1'
	Next
	
	lSize = iConstRun
	
	Do While lSize <= n-1
		For lBegin = 0 To n - 1 Step 2 * lSize      '<-- should be done like this
			lEnd = Min(lBegin + 2 * lSize - 1, n - 1)
			lMid = lBegin + lSize - 1
			If lMid < lEnd Then                     '<-- Add this condition to prevent crashes when size is not a multiple of run.
				TimMergeLong_IDX(arrLong, arrIndex, lBegin, lMid, lEnd)
			End If
		Next
		lSize = lSize * 2
	Loop
	
	Return arrIndex
	
End Sub

Sub TimSortString_IDX(arrString() As String, bCaseInsensitive As Boolean) As Int()
	
	Dim i As Int
	Dim n As Int
	Dim lSize As Int
	Dim lBegin As Int
	Dim lEnd As Int
	Dim lMid As Int
	Dim iConstRun As Int = 32
	
	n = arrString.Length
	
	If Check1DStringAllSame(arrString, bCaseInsensitive, -1, -1) Then
		Dim arrIndex(1) As Int
		arrIndex(0) = -1
		Return arrIndex
	Else
		Dim arrIndex(arrString.Length) As Int
	End If
	
	For i = 0 To n - 1
		arrIndex(i) = i
	Next
	
	For i = 0 To n - 1 Step iConstRun
		TimInsertionString_IDX(arrString, arrIndex, i, Min(i + iConstRun - 1, n - 1), bCaseInsensitive)   '<---- HERE, replace '31' by 'iConstRun-1'
	Next
	
	lSize = iConstRun
	
	Do While lSize <= n-1
		For lBegin = 0 To n - 1 Step 2 * lSize      '<-- should be done like this
			lEnd = Min(lBegin + 2 * lSize - 1, n - 1)
			lMid = lBegin + lSize - 1
			If lMid < lEnd Then                     '<-- Add this condition to prevent crashes when size is not a multiple of run.
				TimMergeString_IDX(arrString, arrIndex, lBegin, lMid, lEnd, bCaseInsensitive)
			End If
		Next
		lSize = lSize * 2
	Loop
	
	Return arrIndex
	
End Sub

Sub TimInsertionInt_IDX(arrInt() As Int, arrIndex() As Int, lBegin As Int, lEnd As Int)
	
	Dim i As Int
	Dim j As Int
	Dim lTemp As Int
	
	For i = lBegin + 1 To lEnd
		lTemp = arrInt(arrIndex(i))
		j = i - 1
		Do While CheckWhileInt(j, lBegin, arrInt, arrIndex, lTemp)
			arrIndex(j + 1) = arrIndex(j)
			j = j - 1
		Loop
		arrIndex(j + 1) = i
	Next
	
End Sub

Sub TimInsertionDouble_IDX(arrDouble() As Double, arrIndex() As Int, lBegin As Int, lEnd As Int)
	
	Dim i As Int
	Dim j As Int
	Dim dTemp As Double
	
	For i = lBegin + 1 To lEnd
		dTemp = arrDouble(arrIndex(i))
		j = i - 1
		Do While CheckWhileDouble(j, lBegin, arrDouble, arrIndex, dTemp)
			arrIndex(j + 1) = arrIndex(j)
			j = j - 1
		Loop
		arrIndex(j + 1) = i
	Next
	
End Sub

Sub TimInsertionLong_IDX(arrLong() As Long, arrIndex() As Int, lBegin As Int, lEnd As Int)
	
	Dim i As Int
	Dim j As Int
	Dim lTemp As Long
	
	For i = lBegin + 1 To lEnd
		lTemp = arrLong(arrIndex(i))
		j = i - 1
		Do While CheckWhileLong(j, lBegin, arrLong, arrIndex, lTemp)
			arrIndex(j + 1) = arrIndex(j)
			j = j - 1
		Loop
		arrIndex(j + 1) = i
	Next
	
End Sub

Sub TimInsertionString_IDX(arrString() As String, arrIndex() As Int, lBegin As Int, lEnd As Int, bCaseInsensitive As Boolean)
	
	Dim i As Int
	Dim j As Int
	Dim strTemp As String
	
	If bCaseInsensitive Then
		strTemp = arrString(arrIndex(i)).ToLowerCase
		j = i - 1
		Do While CheckWhileString(j, lBegin, arrString, arrIndex, strTemp, True)
			arrIndex(j + 1) = arrIndex(j)
			j = j - 1
		Loop
		arrIndex(j + 1) = i
	Else
		For i = lBegin + 1 To lEnd
			strTemp = arrString(arrIndex(i))
			j = i - 1
			Do While CheckWhileString(j, lBegin, arrString, arrIndex, strTemp, False)
				arrIndex(j + 1) = arrIndex(j)
				j = j - 1
			Loop
			arrIndex(j + 1) = i
		Next
	End If
	
End Sub

Sub CheckWhileInt(j As Int, lBegin As Int, arrInt() As Int, arrIndex() As Int, lTemp As Int) As Boolean
	
	If j < 0 Then
		Return False
	End If
	
	If j >= lBegin Then
		If arrInt(arrIndex(j)) > lTemp Then
			Return True
		End If
	End If
	
	Return False
End Sub

Sub CheckWhileDouble(j As Int, lBegin As Int, arrDouble() As Double, arrIndex() As Int, dTemp As Double) As Boolean
	
	If j < 0 Then
		Return False
	End If
	
	If j >= lBegin Then
		If arrDouble(arrIndex(j)) > dTemp Then
			Return True
		End If
	End If
	
	Return False
End Sub

Sub CheckWhileLong(j As Int, lBegin As Int, arrLong() As Long, arrIndex() As Int, lTemp As Long) As Boolean
	
	If j < 0 Then
		Return False
	End If
	
	If j >= lBegin Then
		If arrLong(arrIndex(j)) > lTemp Then
			Return True
		End If
	End If
	
	Return False
End Sub

Sub CheckWhileString(j As Int, lBegin As Int, arrString() As String, arrIndex() As Int, strTemp As String, bcaseInsensitive As Boolean) As Boolean
	
	If j < 0 Then
		Return False
	End If
	
	If bcaseInsensitive Then
		If j >= lBegin Then
			If arrString(arrIndex(j)).ToLowerCase.CompareTo(strTemp) > 0 Then
				Return True
			End If
		End If
	Else
		If j >= lBegin Then
			If arrString(arrIndex(j)).CompareTo(strTemp) > 0 Then
				Return True
			End If
		End If
	End If
	
	Return False
End Sub

Sub TimMergeInt_IDX(arrInt() As Int, arrIndex() As Int, lLeft As Int, lMid As Int, lRight As Int)
	
	Dim i As Int
	Dim j As Int
	Dim k As Int
	Dim Len1 As Int
	Dim Len2 As Int
	Len1 = lMid - lLeft + 1
	Len2 = lRight - lMid
	Dim arrBegin(Len1) As Int
	Dim arrEnd(Len2) As Int

	For i = 0 To Len1 - 1
		arrBegin(i) = arrIndex(lLeft + i)
	Next
	
	For i = 0 To Len2 - 1
		arrEnd(i) = arrIndex(lMid + 1 + i)
	Next
	
	i = 0
	j = 0
	k = lLeft
	
	Do While i < Len1 And j < Len2
		If arrInt(arrBegin(i)) <= arrInt(arrEnd(j)) Then
			arrIndex(k) = arrBegin(i)
			i = i + 1
		Else
			arrIndex(k) = arrEnd(j)
			j = j + 1
		End If
		k = k + 1
	Loop

	
	Do While i < Len1
		arrIndex(k) = arrBegin(i)
		k = k + 1
		i = i + 1
	Loop
	
	Do While j < Len2
		arrIndex(k) = arrEnd(j)
		k = k + 1
		j = j + 1
	Loop
	
End Sub

Sub TimMergeDouble_IDX(arrDouble() As Double, arrIndex() As Int, lLeft As Int, lMid As Int, lRight As Int)
	
	Dim i As Int
	Dim j As Int
	Dim k As Int
	Dim Len1 As Int
	Dim Len2 As Int
	
	Len1 = lMid - lLeft + 1
	Len2 = lRight - lMid
	
	Dim arrBegin(Len1) As Int
	Dim arrEnd(Len2) As Int

	For i = 0 To Len1 - 1
		arrBegin(i) = arrIndex(lLeft + i)
	Next
	
	For i = 0 To Len2 - 1
		arrEnd(i) = arrIndex(lMid + 1 + i)
	Next
	
	i = 0
	j = 0
	k = lLeft
	
	Do While i < Len1 And j < Len2
		If arrDouble(arrBegin(i)) <= arrDouble(arrEnd(j)) Then
			arrIndex(k) = arrBegin(i)
			i = i + 1
		Else
			arrIndex(k) = arrEnd(j)
			j = j + 1
		End If
		k = k + 1
	Loop

	
	Do While i < Len1
		arrIndex(k) = arrBegin(i)
		k = k + 1
		i = i + 1
	Loop
	
	Do While j < Len2
		arrIndex(k) = arrEnd(j)
		k = k + 1
		j = j + 1
	Loop
	
End Sub

Sub TimMergeLong_IDX(arrLong() As Long, arrIndex() As Int, lLeft As Int, lMid As Int, lRight As Int)
	
	Dim i As Int
	Dim j As Int
	Dim k As Int
	Dim Len1 As Int
	Dim Len2 As Int
	
	Len1 = lMid - lLeft + 1
	Len2 = lRight - lMid
	
	Dim arrBegin(Len1) As Int
	Dim arrEnd(Len2) As Int

	For i = 0 To Len1 - 1
		arrBegin(i) = arrIndex(lLeft + i)
	Next
	
	For i = 0 To Len2 - 1
		arrEnd(i) = arrIndex(lMid + 1 + i)
	Next
	
	i = 0
	j = 0
	k = lLeft
	
	Do While i < Len1 And j < Len2
		If arrLong(arrBegin(i)) <= arrLong(arrEnd(j)) Then
			arrIndex(k) = arrBegin(i)
			i = i + 1
		Else
			arrIndex(k) = arrEnd(j)
			j = j + 1
		End If
		k = k + 1
	Loop
	
	Do While i < Len1
		arrIndex(k) = arrBegin(i)
		k = k + 1
		i = i + 1
	Loop
	
	Do While j < Len2
		arrIndex(k) = arrEnd(j)
		k = k + 1
		j = j + 1
	Loop
	
End Sub

Sub TimMergeString_IDX(arrString() As String, arrIndex() As Int, lLeft As Int, lMid As Int, lRight As Int, bCaseInsensitive As Boolean)
	
	Dim i As Int
	Dim j As Int
	Dim k As Int
	Dim Len1 As Int
	Dim Len2 As Int
	Len1 = lMid - lLeft + 1
	Len2 = lRight - lMid
	Dim arrBegin(Len1) As Int
	Dim arrEnd(Len2) As Int

	For i = 0 To Len1 - 1
		arrBegin(i) = arrIndex(lLeft + i)
	Next
	
	For i = 0 To Len2 - 1
		arrEnd(i) = arrIndex(lMid + 1 + i)
	Next
	
	i = 0
	j = 0
	k = lLeft
	
	If bCaseInsensitive Then
		Do While i < Len1 And j < Len2
			If arrString(arrBegin(i)).ToLowerCase.CompareTo(arrString(arrEnd(j)).ToLowerCase) <= 0 Then
				arrIndex(k) = arrBegin(i)
				i = i + 1
			Else
				arrIndex(k) = arrEnd(j)
				j = j + 1
			End If
			k = k + 1
		Loop
	Else
		Do While i < Len1 And j < Len2
			If arrString(arrBegin(i)).CompareTo(arrString(arrEnd(j))) <= 0 Then
				arrIndex(k) = arrBegin(i)
				i = i + 1
			Else
				arrIndex(k) = arrEnd(j)
				j = j + 1
			End If
			k = k + 1
		Loop
	End If

	
	Do While i < Len1
		arrIndex(k) = arrBegin(i)
		k = k + 1
		i = i + 1
	Loop
	
	Do While j < Len2
		arrIndex(k) = arrEnd(j)
		k = k + 1
		j = j + 1
	Loop
	
End Sub

Sub SortB4XOMByIntValues(oB4XOM As B4XOrderedMap, bAscending As Boolean) As B4XOrderedMap  'ignore warning
	
	Dim i As Int
	Dim arrKeys(oB4XOM.Size) As String
	Dim arrValues(oB4XOM.Size) As Int
	Dim arrIndex() As Int
	Dim oB4XOMSorted As B4XOrderedMap
	
	For Each strKey As String In oB4XOM.Keys
		arrKeys(i) = strKey
		arrValues(i) = oB4XOM.Get(strKey)
		i = i + 1
	Next
	
	arrIndex = SortOMIntIDX(arrValues, bAscending, -1, -1)
	
	If arrIndex(0) = -1 Then
		'all values same, so return old B4XOrderedMap
		Return oB4XOM
	End If
	
	oB4XOMSorted.Initialize
	
	For i = 0 To arrIndex.Length - 1
		oB4XOMSorted.Put(arrKeys(arrIndex(i)), arrValues(arrIndex(i)))
	Next
	
	Return oB4XOMSorted
	
End Sub

Sub SortMapByStringKey(oMap As Map, bAscending As Boolean, bCaseInsensitive As Boolean) As Map  'ignore warning
	
	Dim i As Int
	Dim arrKeys(oMap.Size) As String
	Dim arrValues(oMap.Size) As Object
	Dim arrIndex() As Int
	Dim oMapSorted As Map
	
	For Each strkey In oMap.Keys
		arrKeys(i) = strkey
		arrValues(i) = oMap.Get(strkey)
		i = i + 1
	Next
	
	arrIndex = SortOMStringIDX(arrKeys, bAscending, bCaseInsensitive, -1, -1)
	
	oMapSorted.Initialize
	
	For i = 0 To arrIndex.Length - 1
		oMapSorted.Put(arrKeys(arrIndex(i)), arrValues(arrIndex(i)))
	Next
	
	Return oMapSorted
	
End Sub

Sub ReverseIndexLong(arrLong() As Long, arrIndex() As Int, bUnique As Boolean) As Int()
	
	Dim i As Int
	Dim c As Int
	Dim n As Int
	Dim x As Int
	Dim iUB As Int
	Dim bSame As Boolean
	Dim arrIndex2(arrLong.Length) As Int
	
	iUB = arrLong.Length - 1
	
	If bUnique Then
		'do a simple reverse
		For i = 0 To iUB
			arrIndex2(iUB - i) = arrIndex(i)
		Next
		Return arrIndex2
	Else
		For i = 0 To iUB
			If i < iUB Then
				bSame = arrLong(arrIndex(i)) = arrLong(arrIndex(i + 1))
			Else
				bSame = arrLong(arrIndex(i)) = arrLong(arrIndex(i - 1))
			End If
			If bSame Then
				c = c + 1
				If i = iUB Then
					x = 0
					For n = (i - c) + 1 To i
						arrIndex2(x) = arrIndex(n)
						x = x + 1
					Next
					Return arrIndex2
				End If
			Else
				If c > 0 Then
					x = 0
					For n = i - c To i
						arrIndex2((iUB - i) + x) = arrIndex(n)
						x = x + 1
					Next
					c = 0
				Else 'If c > 0
					arrIndex2(iUB - i) = arrIndex(i)
				End If 'If c > 0
			End If
		Next
	End If
	
	Return arrIndex2
	
End Sub

Sub ReverseIndexDouble(arrDouble() As Double, arrIndex() As Int, bUnique As Boolean) As Int()
	
	Dim i As Int
	Dim c As Int
	Dim n As Int
	Dim x As Int
	Dim iUB As Int
	Dim bSame As Boolean
	Dim arrIndex2(arrDouble.Length) As Int
	
	iUB = arrDouble.Length - 1
	
	If bUnique Then
		'do a simple reverse
		For i = 0 To iUB
			arrIndex2(iUB - i) = arrIndex(i)
		Next
		Return arrIndex2
	Else
		For i = 0 To iUB
			If i < iUB Then
				bSame = arrDouble(arrIndex(i)) = arrDouble(arrIndex(i + 1))
			Else
				bSame = arrDouble(arrIndex(i)) = arrDouble(arrIndex(i - 1))
			End If
			If bSame Then
				c = c + 1
				If i = iUB Then
					x = 0
					For n = (i - c) + 1 To i
						arrIndex2(x) = arrIndex(n)
						x = x + 1
					Next
					Return arrIndex2
				End If
			Else
				If c > 0 Then
					x = 0
					For n = i - c To i
						arrIndex2((iUB - i) + x) = arrIndex(n)
						x = x + 1
					Next
					c = 0
				Else 'If c > 0
					arrIndex2(iUB - i) = arrIndex(i)
				End If 'If c > 0
			End If
		Next
	End If
	
	Return arrIndex2
	
End Sub

Sub ReverseIndexString(arrString() As String, arrIndex() As Int, bUnique As Boolean) As Int()
	
	Dim i As Int
	Dim c As Int
	Dim n As Int
	Dim x As Int
	Dim iUB As Int
	Dim bSame As Boolean
	Dim arrIndex2(arrString.Length) As Int
	
	iUB = arrString.Length - 1
	
	If bUnique Then
		'do a simple reverse
		For i = 0 To iUB
			arrIndex2(iUB - i) = arrIndex(i)
		Next
		Return arrIndex2
	Else 'If bUnique
		For i = 0 To iUB
			If i < iUB Then
				bSame = arrString(arrIndex(i)) = arrString(arrIndex(i + 1))
			Else
				bSame = arrString(arrIndex(i)) = arrString(arrIndex(i - 1))
			End If
			If bSame Then
				c = c + 1
				If i = iUB Then
					x = 0
					For n = (i - c) + 1 To i
						arrIndex2(x) = arrIndex(n)
						x = x + 1
					Next
					Return arrIndex2
				End If
			Else 'If bSame Then
				If c > 0 Then
					x = 0
					For n = i - c To i
						arrIndex2((iUB - i) + x) = arrIndex(n)
						x = x + 1
					Next

					c = 0
				Else 'If c > 0
					arrIndex2(iUB - i) = arrIndex(i)
				End If 'If c > 0
			End If 'If bSame Then
		Next
	End If 'If bUnique
	
	Return arrIndex2
	
End Sub