Passing an array to a function: any way to make it type-independent? - page 2

 
2cent:

Here some dirty trick, just for the fun of it.. uses a system dll's memcpy.

Very interesting. Thank you :)
 

I've performed the following speed test. Time it takes to Append TenMillion integers to beginning of Array using methods described within this thread.

2014.01.03 00:01:45 TestingB EURUSD,M1: Number Of MilliSeconds To Complete Using Original Post=3853 ... Non-Beta
2014.01.03 00:03:05 TestingB EURUSD,M1: Number Of MilliSeconds To Complete Using RaptorUK Suggestion=6100 ... Non-Beta
2014.01.03 00:04:45 TestingB EURUSD,M1: Number Of MilliSeconds To Complete Using ArrayCopy Into Another Array=4930 ... Non-Beta

Then I decided to see how the .dll version would perform. Was running into compile problems on Current mt4, so I decided to use the Beta Built 568 as intended.

2014.01.03 00:38:50.342 TestingC EURUSD,M1: Number Of MilliSeconds To Complete Using 2cent .Dll Method=1638... Beta.


Something else I'd like to point out at this time is that my original intend was the testing of Switch vs OverLoading, using RaptorUK's method. The method works in Current mt4. However it doesn't work in mt4-Beta ... nor mt5. Example:

//  [0] -> { A , B , C , D }
ArraySetAsSeries( vector, true )                
// { A , B , C , D } <- [0]
ArrayResize( vector, ArraySize(vector)+1 ) 
// { _ , A , B , C , D } <- [0]
ArraySetAsSeries( vector, false )               
// [0] -> { _ , A , B , C , D }
ArrayResize( vector, ArraySize(vector)-1 ) //When this happens, Beta && MT5 will remove the Index it just created.
// [0] -> { _ , A , B , C } // Ends up looking like this instead. {A , B , C , D} trimming from the left side.
vector[0] = K               // K ends up OverWriting A
//  [0] ->{ K , A , B , C } // Instead you get {K, B, C, D}

It appears that current mt4 always resizes from the Right. But the new terminals resize from the direction of the Series. I liked the above solution because it seemed like an easy way of creating Buffer like behavior. I cannot think up a solution for this ... and I would be interested to know if someone has an answer.

About the OverLoad vs Switch thing. Tho I haven't gotten far enough for testing the speed, it appears that Overloading would be a better option. The Switch requires Dummy Parameters (like a dummy double_array) when all I'm wanting to work with is Integer_Arrays. Also needed to pass a Dummy Double Value and the Switch. The number of parameters to pass could get out of control as the list grows. So its not looking attractive so far.

 

Finally got around to testing the speed of Switch vs Overload. The following results below using Beta and MT5. Ten_Million Appending. Appending method used was the Original_Post i.e vector[i] = vector[i-1].

2014.01.03 06:49:11.005 TestingD EURUSD,M1: Number Of MilliSeconds To Complete Using Switch=1404 ... Beta 568
2014.01.03 07:30:03.335 TestingD EURUSD,M1: Number Of MilliSeconds To Complete Using Overload=1232 ... Beta 568

2014.01.03 07:41:11.744 TestingD (EURUSD,M1) Number Of MilliSeconds To Complete Using Switch=562 ... MT5 880
2014.01.03 07:36:37.328 TestingD (EURUSD,M1) Number Of MilliSeconds To Complete Using Overload=515 ... MT5 880

Appears like the speed from the .Dll version earlier was faster because Beta is probably* faster then Current_MT4. With MT5 being the fastest.

I'll opt for Overloading for the reasons I'd stated earlier.

 
On more: circular buffer

With circular buffer it is chap performance-wise to insert elements to front and lose last element.
However, sequential read/write is somewhat more costly; also one has to maintain an index to the front element and perferably use a buffer size of a power of 2:

Insert element to front with cbuffer:
// script

int cbuf[4] = {1, 2, 3, 4};
const int cbuf_size_minus_1 = 4-1;
int index_of_first = 0;

void push_front(int element)
{
        index_of_first = index_of_first - 1 & cbuf_size_minus_1;
        cbuf[index_of_first] = element;
}

void OnStart()
{
        push_front(4);
        push_front(3);
        for(int i = 0; i < ArraySize(cbuf); i++)
                Print(cbuf[index_of_first + i & cbuf_size_minus_1]);
                
}
 
2cent:
On more: circular buffer

With circular buffer it is chap performance-wise to insert elements to front and lose last element.
However, sequential read/write is somewhat more costly; also one has to maintain an index to the front element and perferably use a buffer size of a power of 2:

Insert element to front with cbuffer:

What type of Voodoo is this... thank you. I'll need to study Bitwise AND (&) some more to fully understand.

Why did you remove the Second example you had about ArrayResize ?

 
Well I realized that it was slow, so no point in presenting it. The test for overflow dragged it down too much. This is what makes the circular buffer with a size of a power of two (and only such a size) fast: the wrap-around can be handled with a cheap bit-wise and with size-1 - so no slow if-statement there.
 
2cent: Well I realized that it was slow, so no point in presenting it. The test for overflow dragged it down too much. This is what makes the circular buffer with a size of a power of two (and only such a size) fast: the wrap-around can be handled with a cheap bit-wise and with size-1 - so no slow if-statement there.

K... Noted.

 

If anyone's interested in the codes I've used to generate my results ... look below. It has most of what's used.

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void OnStart(){
    int iMaxSize=5;
    int iTenMillion=10000000;
    int iDynArray1[];
    CArrayPrepend* obj1 = new CArrayPrepend;
    
    ArrayResize(iDynArray1,iMaxSize);
    iDynArray1[0]=0;
    iDynArray1[1]=1;
    iDynArray1[2]=2;
    iDynArray1[3]=3;
    iDynArray1[4]=4;
    ArraySetAsSeries(iDynArray1,false);
    
    double dDummyArray[];
    uint iBegin=GetTickCount();
    
    for(int i=0; i<iTenMillion; i++)
        obj1.ArrayPrependOverload(iDynArray1,i);
    
    uint iFinish=GetTickCount()-iBegin;
    Print("Number Of MilliSeconds To Complete Using =",iFinish);
    PrintIntegerArrayContents(iDynArray1,5);
    delete obj1; obj1=NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*void ArrayPrependSwitch(
    int cSwitch, 
    int& iArray[], 
    int iValue, 
    double& dArray[], 
    double dValue
){
    switch(cSwitch){
        case 'i': ArrayPrependInteger(iArray, iValue);      return;
        case 'd': ArrayPrependDouble(dArray, dValue);       return;
    }
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ArrayPrependInteger(int& vector[], int val){
    for( int i=ArraySize(vector)-1 ; i>0 ; i-- ) vector[i] = vector[i-1];
    vector[0] = val;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ArrayPrependDouble(double& vector[], double val){
    for( int i=ArraySize(vector)-1 ; i>0 ; i-- ) vector[i] = vector[i-1];
    vector[0] = val;
}*/
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class CArrayPrepend{
    private:
    public:
        CArrayPrepend(){}; //Constructor
        ~CArrayPrepend(){}; //Destructor
        void ArrayPrependOverload(int& vector[], int val);
        void ArrayPrependOverload(double& vector[], double val);
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void CArrayPrepend::ArrayPrependOverload(int& vector[], int val){
    for( int i=ArraySize(vector)-1 ; i>0 ; i-- ) vector[i] = vector[i-1];
    vector[0] = val;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void CArrayPrepend::ArrayPrependOverload(double& vector[], double val){
    for( int i=ArraySize(vector)-1 ; i>0 ; i-- ) vector[i] = vector[i-1];
    vector[0] = val;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void PrintIntegerArrayContents(int& iDynamicArray[], int iSampleSize){
    int iCounter=0;
    for(int i=ArraySize(iDynamicArray)-1; i>=0; i--){
        Print("i=",i,"___Value=",iDynamicArray[i]); iCounter++;
        if(iCounter>=iSampleSize) break;
    }
    Print("_________________________________");
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*void PrintDoubleArrayContents(double& dDynamicArray[], int iSampleSize){
    int iCounter=0;
    for(int i=ArraySize(dDynamicArray)-1; i>=0; i--){
        Print("i=",i,"___Value=",dDynamicArray[i]); iCounter++;
        if(iCounter>=iSampleSize) break;
    }
    Print("_________________________________");
}*/
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ArrayPrependSpeedTestX(int& vector[], int val){
    for( int i=ArraySize(vector) ; i>0 ; i-- ) vector[i] = vector[i-1];
    vector[0] = val;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ArrayPrependSpeedTestY(int& vector[], int val){
    ArraySetAsSeries( vector, true );
    ArrayResize( vector, ArraySize(vector)+1 );
    ArraySetAsSeries( vector, false );
    ArrayResize( vector, ArraySize(vector)-1 );
    vector[0] = val;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ArrayPrependSpeedTestZ(int& vector[], int val){
    int itempArray[]; ArrayResize(itempArray,ArraySize(vector));
    ArrayCopy(itempArray,vector,1,0,ArraySize(vector)-1);
    itempArray[0]=val;
    ArrayCopy(vector,itempArray,0,0,ArraySize(itempArray));
}
 
ubzen: It appears that current mt4 always resizes from the Right. But
No But. My ResizeBuffer has been working for 4 years. You have the asSeries backwards.
Reason: