Add files via upload
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayFunction.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "CompareFunction.mqh"
|
||||
#include <Generic\Interfaces\IComparer.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Searches an entire one-dimensional sorted array for a specific |
|
||||
//| element, using the IComparable<T> generic interface implemented |
|
||||
//| by each element of the array and by the specified object. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T>
|
||||
int ArrayBinarySearch(T &array[],const int start_index,const int count, T value,IComparer<T>*comparer)
|
||||
{
|
||||
int lo=start_index;
|
||||
int hi=start_index+count-1;
|
||||
int size=ArraySize(array);
|
||||
//--- check array size
|
||||
if(size==0)
|
||||
return(-1);
|
||||
//--- check comaparer
|
||||
if(CheckPointer(comparer)==POINTER_INVALID)
|
||||
return(-1);
|
||||
//--- check index
|
||||
if(start_index<0 || count<0 || size-start_index<count)
|
||||
return(-1);
|
||||
//--- bianry search value
|
||||
while(lo<=hi)
|
||||
{
|
||||
int i=lo+((hi-lo)>>1);
|
||||
int order=comparer.Compare(array[i],value);
|
||||
if(order==0)
|
||||
{
|
||||
return(i);
|
||||
}
|
||||
if(order<0)
|
||||
{
|
||||
lo=i+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hi=i-1;
|
||||
}
|
||||
}
|
||||
//--- returns the index of an element nearest in value
|
||||
if(lo>0)
|
||||
return(lo-1);
|
||||
return(lo);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Searches for the specified object and returns the index of its |
|
||||
//| first occurrence in a one-dimensional array. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T>
|
||||
int ArrayIndexOf(T &array[],T value,const int start_index,const int count)
|
||||
{
|
||||
int size=ArraySize(array);
|
||||
//--- check array size
|
||||
if(size==0)
|
||||
return(-1);
|
||||
//--- check start index and count
|
||||
if(start_index<0 || start_index>size ||
|
||||
count<0 || count>size-start_index)
|
||||
return(-1);
|
||||
//--- search value
|
||||
int end_index=start_index+count;
|
||||
for(int i=start_index; i<end_index; i++)
|
||||
{
|
||||
//--- check the value in array is eqaul to specified value
|
||||
if(::Equals(array[i],value))
|
||||
{
|
||||
//--- return fist index
|
||||
return(i);
|
||||
}
|
||||
}
|
||||
//--- return -1 if value not in array
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the index of the last occurrence of a value in a |
|
||||
//| one-dimensional array. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T>
|
||||
int ArrayLastIndexOf(T &array[],T value,const int start_index,const int count)
|
||||
{
|
||||
int size=ArraySize(array);
|
||||
//--- check array size
|
||||
if(size==0)
|
||||
return(-1);
|
||||
//--- check start index and count
|
||||
if(start_index<0 || start_index>=size ||
|
||||
count<0 || count>start_index+1)
|
||||
return(-1);
|
||||
//--- search value
|
||||
int end_index=start_index-count+1;
|
||||
for(int i=start_index; i>=end_index; i--)
|
||||
{
|
||||
//--- check the value in array is eqaul to specified value
|
||||
if(::Equals(array[i],value))
|
||||
{
|
||||
//--- return fist index from the end
|
||||
return (i);
|
||||
}
|
||||
}
|
||||
//--- return -1 if value not in array
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reverses the elements in a range of this array. Following a call |
|
||||
//| to this method, an element in the range given by index and count |
|
||||
//| which was previously located at index i will now be located at |
|
||||
//| index index + (index + count - i - 1). |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T>
|
||||
bool ArrayReverse(T &array[],const int start_index,const int count)
|
||||
{
|
||||
int size=ArraySize(array);
|
||||
//--- check start index and count
|
||||
if(count<0 || size-start_index<count)
|
||||
return(false);
|
||||
//--- reverse elements
|
||||
int i = start_index;
|
||||
int j = start_index + count - 1;
|
||||
while(i<j)
|
||||
{
|
||||
T temp=array[i];
|
||||
array[i] = array[j];
|
||||
array[j] = temp;
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,209 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| CompareFunction.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Generic\Interfaces\IComparable.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const bool x,const bool y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const char x,const char y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const uchar x,const uchar y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const short x,const short y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const ushort x,const ushort y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const color x,const color y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const int x,const int y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const uint x,const uint y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const datetime x,const datetime y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const long x,const long y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const ulong x,const ulong y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const float x,const float y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const double x,const double y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
int Compare(const string x,const string y)
|
||||
{
|
||||
if(x>y)
|
||||
return(1);
|
||||
else if(x<y)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compares two objects and returns a value indicating whether one |
|
||||
//| is less than, equal to, or greater than the other. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T>
|
||||
int Compare(T x,T y)
|
||||
{
|
||||
//--- try to convert to comparable object
|
||||
IComparable<T>*comparable=dynamic_cast<IComparable<T>*>(x);
|
||||
if(comparable)
|
||||
{
|
||||
//--- use specied compare method
|
||||
return comparable.Compare(y);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- unknown compare function
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,22 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DefaultComparer.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Generic\Interfaces\IComparer.mqh>
|
||||
#include "CompareFunction.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CDefaultComparer<T>. |
|
||||
//| Usage: Provides a default class for implementations of the |
|
||||
//| IComparer<T> generic interface. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T>
|
||||
class CDefaultComparer: public IComparer<T>
|
||||
{
|
||||
public:
|
||||
CDefaultComparer(void) { }
|
||||
~CDefaultComparer(void) { }
|
||||
//--- compares two values and returns a value describing relationship between them
|
||||
int Compare(T x,T y) { return ::Compare(x,y); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,25 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DefaultEqualityComparer.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Generic\Interfaces\IEqualityComparer.mqh>
|
||||
#include "EqualFunction.mqh"
|
||||
#include "HashFunction.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CDefaultEqualityComparer<T>. |
|
||||
//| Usage: Provides a default class for implementations of the |
|
||||
//| IEqualityComparer<T> generic interface. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T>
|
||||
class CDefaultEqualityComparer: public IEqualityComparer<T>
|
||||
{
|
||||
public:
|
||||
CDefaultEqualityComparer(void) { }
|
||||
~CDefaultEqualityComparer(void) { }
|
||||
//--- determines whether the specified values are equal
|
||||
bool Equals(T x,T y) { return ::Equals(x,y); }
|
||||
//--- returns a hash code for the specified object
|
||||
int HashCode(T value) { return ::GetHashCode(value); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,26 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| EqualFunction.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Generic\Interfaces\IEqualityComparable.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Indicates whether x object is equal y object of the same type. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T>
|
||||
bool Equals(T x,T y)
|
||||
{
|
||||
//--- try to convert to equality comparable object
|
||||
IEqualityComparable<T>*equtable=dynamic_cast<IEqualityComparable<T>*>(x);
|
||||
if(equtable)
|
||||
{
|
||||
//--- use specied equality compare method
|
||||
return equtable.Equals(y);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- use default equality comparer operator
|
||||
return(x==y);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,176 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HashFunction.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Unioun BitInterpreter. |
|
||||
//| Usage: Provides the ability to interpret the same bit sequence in|
|
||||
//| different types. |
|
||||
//+------------------------------------------------------------------+
|
||||
union BitInterpreter
|
||||
{
|
||||
bool bool_value;
|
||||
char char_value;
|
||||
uchar uchar_value;
|
||||
short short_value;
|
||||
ushort ushort_value;
|
||||
color color_value;
|
||||
int int_value;
|
||||
uint uint_value;
|
||||
datetime datetime_value;
|
||||
long long_value;
|
||||
ulong ulong_value;
|
||||
float float_value;
|
||||
double double_value;
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for boolean. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const bool value)
|
||||
{
|
||||
return((value)?true:false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for character. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const char value)
|
||||
{
|
||||
return((int)value | ((int)value << 16));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for unsigned character. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const uchar value)
|
||||
{
|
||||
return((int)value | ((int)value << 16));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for short. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const short value)
|
||||
{
|
||||
return(((int)((ushort)value) | (((int)value) << 16)));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for unsigned short. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const ushort value)
|
||||
{
|
||||
return((int)value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for color. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const color value)
|
||||
{
|
||||
return((int)value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for integer. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const int value)
|
||||
{
|
||||
return(value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for unsigned integer. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const uint value)
|
||||
{
|
||||
return((int)value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for datetime. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const datetime value)
|
||||
{
|
||||
long ticks=(long)value;
|
||||
return(((int)ticks) ^ (int)(ticks >> 32));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for long. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const long value)
|
||||
{
|
||||
return(((int)((long)value)) ^ (int)(value >> 32));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for unsigned long. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const ulong value)
|
||||
{
|
||||
return(((int)value) ^ (int)(value >> 32));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for float. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const float value)
|
||||
{
|
||||
if(value==0)
|
||||
{
|
||||
//--- ensure that 0 and -0 have the same hash code
|
||||
return(0);
|
||||
}
|
||||
BitInterpreter convert;
|
||||
convert.float_value=value;
|
||||
return(convert.int_value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for string. |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const double value)
|
||||
{
|
||||
if(value==0)
|
||||
{
|
||||
//--- ensure that 0 and -0 have the same hash code
|
||||
return(0);
|
||||
}
|
||||
BitInterpreter convert;
|
||||
convert.double_value=value;
|
||||
long lvalue=convert.long_value;
|
||||
return(((int)lvalue) ^ ((int)(lvalue >> 32)));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for string. |
|
||||
//| The hashcode for a string is computed as: |
|
||||
//| |
|
||||
//| s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] |
|
||||
//| |
|
||||
//| using int arithmetic, where s[i] is the ith character of the |
|
||||
//| string, n is the length of the string, and ^ indicates |
|
||||
//| exponentiation. (The hash value of the empty string is zero.) |
|
||||
//+------------------------------------------------------------------+
|
||||
int GetHashCode(const string value)
|
||||
{
|
||||
int len=StringLen(value);
|
||||
int hash=0;
|
||||
//--- check length of string
|
||||
if(len>0)
|
||||
{
|
||||
//--- calculate a hash as a fucntion of each char
|
||||
for(int i=0; i<len; i++)
|
||||
hash=31*hash+value[i];
|
||||
}
|
||||
return(hash);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns a hashcode for custom object. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T>
|
||||
int GetHashCode(T value)
|
||||
{
|
||||
//--- try to convert to equality comparable object
|
||||
IEqualityComparable<T>*equtable=dynamic_cast<IEqualityComparable<T>*>(value);
|
||||
if(equtable)
|
||||
{
|
||||
//--- calculate hash by specied method
|
||||
return equtable.HashCode();
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- calculate hash from name of object
|
||||
return GetHashCode(typename(value));
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,244 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Introsort.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Struct Introsort<TKey,TItem>. |
|
||||
//| Usage: Used by the sort methods for instances of array. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TKey,typename TItem>
|
||||
struct Introsort
|
||||
{
|
||||
public:
|
||||
IComparer<TKey>* comparer;
|
||||
TKey keys[];
|
||||
TItem items[];
|
||||
|
||||
Introsort(void) {}
|
||||
~Introsort(void) {}
|
||||
//--- method for sort array
|
||||
void Sort(const int index,const int length);
|
||||
private:
|
||||
//--- methods for introspective sorting
|
||||
void IntroSort(const int lo,const int hi,int depthLimit);
|
||||
int PickPivotAndPartition(const int lo,const int hi);
|
||||
void InsertionSort(const int lo,const int hi);
|
||||
//--- methods for heap sorting
|
||||
void Heapsort(const int lo,const int hi);
|
||||
void DownHeap(const int i,const int n,const int lo);
|
||||
//--- swap methods
|
||||
void SwapIfGreaterWithItems(const int a,const int b);
|
||||
void Swap(const int i,const int j);
|
||||
//--- service methods
|
||||
int FloorLog2(int n) const;
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| IntrospectiveSort is a hybrid sorting algorithm that provides |
|
||||
//| both fast average performance and (asymptotically) optimal |
|
||||
//| worst-case performance. It begins with quicksort and switches to |
|
||||
//| heapsort when the recursion depth exceeds a level based on the |
|
||||
//| number of elements being sorted. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TKey,typename TItem>
|
||||
void Introsort::Sort(const int index,const int length)
|
||||
{
|
||||
if(length<2)
|
||||
return;
|
||||
IntroSort(index,length+index-1,2*FloorLog2(ArraySize(keys)));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exchanges the values of a and b, if a greater b. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TKey,typename TItem>
|
||||
void Introsort::SwapIfGreaterWithItems(const int a,const int b)
|
||||
{
|
||||
if(a!=b)
|
||||
{
|
||||
if(comparer.Compare(keys[a],keys[b])>0)
|
||||
{
|
||||
TKey key=keys[a];
|
||||
keys[a]=keys[b];
|
||||
keys[b]=key;
|
||||
if(ArraySize(items)!=NULL)
|
||||
{
|
||||
TItem item=items[a];
|
||||
items[a]=items[b];
|
||||
items[b]=item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exchanges the values of a and b. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TKey,typename TItem>
|
||||
void Introsort::Swap(const int i,const int j)
|
||||
{
|
||||
TKey key=keys[i];
|
||||
keys[i]=keys[j];
|
||||
keys[j]=key;
|
||||
if(ArraySize(items)!=NULL)
|
||||
{
|
||||
TItem item=items[i];
|
||||
items[i]=items[j];
|
||||
items[j]=item;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the closest integer value less than or equal to the base |
|
||||
//| 2 log of the input value. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TKey,typename TItem>
|
||||
int Introsort::FloorLog2(int n) const
|
||||
{
|
||||
int result=0;
|
||||
while(n>=1)
|
||||
{
|
||||
result++;
|
||||
n=n/2;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Introspective sort. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TKey,typename TItem>
|
||||
void Introsort::IntroSort(const int lo,int hi,int depthLimit)
|
||||
{
|
||||
const int IntrosortSizeThreshold=16;
|
||||
while(hi>lo)
|
||||
{
|
||||
int partitionSize = hi - lo + 1;
|
||||
if(partitionSize <= IntrosortSizeThreshold)
|
||||
{
|
||||
if(partitionSize==1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(partitionSize==2)
|
||||
{
|
||||
SwapIfGreaterWithItems(lo,hi);
|
||||
return;
|
||||
}
|
||||
if(partitionSize==3)
|
||||
{
|
||||
SwapIfGreaterWithItems(lo,hi-1);
|
||||
SwapIfGreaterWithItems(lo,hi);
|
||||
SwapIfGreaterWithItems(hi-1,hi);
|
||||
return;
|
||||
}
|
||||
InsertionSort(lo,hi);
|
||||
return;
|
||||
}
|
||||
if(depthLimit==0)
|
||||
{
|
||||
Heapsort(lo,hi);
|
||||
return;
|
||||
}
|
||||
depthLimit--;
|
||||
int p=PickPivotAndPartition(lo,hi);
|
||||
IntroSort(p+1,hi,depthLimit);
|
||||
hi=p-1;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Insertion sort. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TKey,typename TItem>
|
||||
void Introsort::InsertionSort(const int lo,const int hi)
|
||||
{
|
||||
int i,j;
|
||||
TKey t;
|
||||
TItem dt;
|
||||
for(i=lo; i<hi; i++)
|
||||
{
|
||||
j = i;
|
||||
t = keys[i + 1];
|
||||
dt=(ArraySize(items)!=NULL) ? (TItem)items[i+1] : (TItem)NULL;
|
||||
while(j>=lo && comparer.Compare(t,keys[j])<0)
|
||||
{
|
||||
keys[j+1]=keys[j];
|
||||
if(ArraySize(items)!=NULL)
|
||||
{
|
||||
items[j+1]=items[j];
|
||||
}
|
||||
j--;
|
||||
}
|
||||
keys[j+1]=t;
|
||||
if(ArraySize(items)!=NULL)
|
||||
{
|
||||
items[j+1]=dt;
|
||||
}
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Array partitioning by a quick sort algorithm. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TKey,typename TItem>
|
||||
int Introsort::PickPivotAndPartition(const int lo,const int hi)
|
||||
{
|
||||
//--- Compute median-of-three. But also partition them, since we've done the comparison.
|
||||
int mid=lo+(hi-lo)/2;
|
||||
SwapIfGreaterWithItems(lo,mid);
|
||||
SwapIfGreaterWithItems(lo,hi);
|
||||
SwapIfGreaterWithItems(mid,hi);
|
||||
TKey pivot=keys[mid];
|
||||
Swap(mid,hi-1);
|
||||
int left=lo,right=hi-1;
|
||||
while(left<right)
|
||||
{
|
||||
while(comparer.Compare(keys[++left], pivot) < 0);
|
||||
while(comparer.Compare(pivot, keys[--right]) < 0);
|
||||
if(left>=right)
|
||||
break;
|
||||
Swap(left,right);
|
||||
}
|
||||
//--- Put pivot in the right location.
|
||||
Swap(left,(hi-1));
|
||||
return (left);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Heap sorting algorithm. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TKey,typename TItem>
|
||||
void Introsort::Heapsort(const int lo,const int hi)
|
||||
{
|
||||
int n=hi-lo+1;
|
||||
for(int i=n/2; i>=1; i=i-1)
|
||||
{
|
||||
DownHeap(i,n,lo);
|
||||
}
|
||||
for(int i=n; i>1; i=i-1)
|
||||
{
|
||||
Swap(lo,lo+i-1);
|
||||
DownHeap(1,i-1,lo);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Downheap function for heapsort. |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TKey,typename TItem>
|
||||
void Introsort::DownHeap(int i,const int n,const int lo)
|
||||
{
|
||||
bool f=ArraySize(items)!=0;
|
||||
TKey d=keys[lo+i-1];
|
||||
TItem dt=f ? (TItem)items[lo+i-1] : (TItem)NULL;
|
||||
|
||||
while(i<=n/2)
|
||||
{
|
||||
int child=2*i;
|
||||
if(child<n && comparer.Compare(keys[lo+child-1],keys[lo+child])<0)
|
||||
child++;
|
||||
if(!(comparer.Compare(d,keys[lo+child-1])<0))
|
||||
break;
|
||||
keys[lo+i-1]=keys[lo+child-1];
|
||||
if(f)
|
||||
items[lo+i-1]=items[lo+child-1];
|
||||
i=child;
|
||||
}
|
||||
keys[lo+i-1]=d;
|
||||
if(f)
|
||||
items[lo+i-1]=dt;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,81 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| PrimeGenerator.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CPrimeGenrator. |
|
||||
//| Usage: Used to generate prime numbers. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CPrimeGenerator
|
||||
{
|
||||
private:
|
||||
const static int s_primes[]; // table of prime numbers
|
||||
const static int s_hash_prime;
|
||||
|
||||
public:
|
||||
static bool IsPrime(const int candidate);
|
||||
static int GetPrime(const int min);
|
||||
static int ExpandPrime(const int old_size);
|
||||
};
|
||||
const static int CPrimeGenerator::s_primes[]=
|
||||
{
|
||||
3,7,11,17,23,29,37,47,59,71,89,107,131,163,197,239,293,353,431,521,631,761,919,
|
||||
1103,1327,1597,1931,2333,2801,3371,4049,4861,5839,7013,8419,10103,12143,14591,
|
||||
17519,21023,25229,30293,36353,43627,52361,62851,75431,90523,108631,130363,156437,
|
||||
187751,225307,270371,324449,389357,467237,560689,672827,807403,968897,1162687,1395263,
|
||||
1674319,2009191,2411033,2893249,3471899,4166287,4999559,5999471,7199369,8332579,
|
||||
9999161,11998949,14398753,16665163,19998337,23997907,28797523,33330329,39996683,
|
||||
47995853,57595063,66660701,79993367,95991737,115190149,133321403,159986773,191983481,
|
||||
230380307,266642809,319973567,383966977,460760623,533285671,639947149,767933981,
|
||||
921521257,1066571383,1279894313,1535867969,1843042529,2133142771
|
||||
};
|
||||
const static int CPrimeGenerator::s_hash_prime=101;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Determines whether a value is prime. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPrimeGenerator::IsPrime(const int candidate)
|
||||
{
|
||||
if((candidate&1)!=0)
|
||||
{
|
||||
int limit=(int)MathSqrt(candidate);
|
||||
//--- check value is prime
|
||||
for(int divisor=3; divisor<=limit; divisor+=2)
|
||||
if((candidate%divisor)==0)
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
return(candidate==2);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Fast generator of prime value. |
|
||||
//+------------------------------------------------------------------+
|
||||
int CPrimeGenerator::GetPrime(const int min)
|
||||
{
|
||||
//--- a typical resize algorithm would pick the smallest prime number in this array
|
||||
//--- that is larger than twice the previous capacity.
|
||||
//--- get next prime value from table
|
||||
for(int i=0; i<ArraySize(s_primes); i++)
|
||||
{
|
||||
int prime=s_primes[i];
|
||||
if(prime>=min)
|
||||
return(prime);
|
||||
}
|
||||
//--- outside of our predefined table
|
||||
for(int i=(min|1); i<=INT_MAX;i+=2)
|
||||
{
|
||||
if(IsPrime(i) && ((i-1)%s_hash_prime!=0))
|
||||
return(i);
|
||||
}
|
||||
return(min);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generate a new prime value greater than old_size. |
|
||||
//+------------------------------------------------------------------+
|
||||
int CPrimeGenerator::ExpandPrime(const int old_size)
|
||||
{
|
||||
if(old_size>=INT_MAX/2)
|
||||
return(INT_MAX);
|
||||
return(GetPrime(old_size*2));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Reference in New Issue
Block a user