main.cpp

#include "stdafx.h"
#include "testing.h"
using namespace std;




void testUninitialisedArray() {
    // Create an unintialised of length 5
    int myArray[5];
    for (int i=0; i<5; i++) {
        cout<<"Entry "<<i<<"=";
        cout<<myArray[i];
        cout<<"\n";
    }
}

void testInitialisedArray() {
    // Create an initialised array
    int myArray[] = {1, 1, 2, 3, 5};
    for (int i=0; i<5; i++) {
        cout<<"Entry "<<i<<"=";
        cout<<myArray[i];
        cout<<"\n";
    }
}

void testInitialisedWithZeroArray() {
    // Create an initialised array
    int myArray[5] = {};
    for (int i=0; i<5; i++) {
        cout<<"Entry "<<i<<"=";
        cout<<myArray[i];
        cout<<"\n";
    }
}

void testArrayLengthBiggerThanData() {
    int myArray[5] = {1,2,3};
    for (int i=0; i<5; i++) {
        cout<<"Entry "<<i<<"=";
        cout<<myArray[i];
        cout<<"\n";
    }
}



void test2DArray() {

    // Create an initialised 3x5 array
    int myArray[][5] = {{1, 2, 3, 4, 5},
                       {2, 0, 0, 0, 0},
                       {3, 0, 0, 0, 0}};
    for (int i=0; i<3; i++) {
        for (int j=0; j<5; j++) {
            cout<<"Entry ("<<i<<","<<j<<")=";
            cout<<myArray[i][j];
            cout<<"\n";
        }
    }
}


// User has to tell us the length
int sumArray( int toSum[], int length ) {
    int sum = 0;
    for (int i=0; i<length; i++) {
        sum+=toSum[i];
    }
    return sum;
}

void testUsingAnArray() {
    int n = 10;
    int tenSquares[10];
    // this doesn't work!
    // int tenSquares[n];
    for (int i=0; i<n; i++) {
        tenSquares[i] = i*i;
    }
    int sum = sumArray( tenSquares, n );
    cout<<"Sum="<<sum<<"\n";
}



void testVariableSizeData() {
    int n = 5;
    int* myArray = new int[n];
    for (int i=0; i<n; i++) {
        cout<<"Entry "<<i<<"=";
        cout << myArray[i];
        cout << "\n";
    }
    delete[] myArray;
}

void testPointerExample() {

    int myVariable = 10;
    int* pointerToMyVariable = &myVariable;

    cout << "Memory location of myVariable ";
    cout << pointerToMyVariable;
    cout << "\n";

    cout << "Value of myVariable ";
    cout << (*pointerToMyVariable);
    cout << "\n";

}


// User has to tell us the length
int sumUsingPointer( int* toSum, int length ) {
    int sum = 0;
    for (int i=0; i<length; i++) {
        sum+=toSum[i];
    }
    return sum;
}


// User has to tell us the length
int sumUsingPointerArithmetic( int* toSum,
                               int length ) {
    int sum = 0;
    for (int i=0; i<length; i++) {
		int* ithElement = toSum + i;
        int valueOfIthElement = *ithElement;
        sum+= valueOfIthElement;
    }
    return sum;
}
int sumUsingPlusPlus( int* firstElement, int n) {
    int sum = 0;
    int* pointer = firstElement;
    int* oneAfterEnd = firstElement + n;
    while (pointer!=oneAfterEnd) {
        sum += *pointer;
        pointer++;
    }
    return sum;
}

int sumUsingForAndPlusPlus(int* begin, int n) {
	int sum = 0;
	int* end = begin + n;
	for (int* ptr = begin; ptr != end; ptr++) {
        sum += *ptr;
	}
	return sum;	
}





void testUsingPointers() {
    int n = 10;
    int* nSquares = new int[n];
    for (int i=0; i<n; i++) {
        nSquares[i] = i*i;
    }
    int sum1 = sumArray( nSquares, n );
    int sum2 = sumUsingPointer( nSquares, n );
    int sum3 = sumUsingPointerArithmetic( nSquares, n );
    int sum4 = sumUsingPlusPlus( nSquares, n );
    int sum5 = sumUsingForAndPlusPlus( nSquares, n );
    cout<<"Sum1="<<sum1<<"\n";
    cout<<"Sum2="<<sum2<<"\n";
    cout<<"Sum3="<<sum3<<"\n";
    cout<<"Sum4="<<sum4<<"\n";
    cout<<"Sum5="<<sum5<<"\n";
    delete[] nSquares;
}

void testCharArray() {
    char charArray1[] =
        {'H', 'e', 'l', 'l', 'o', '\0' };
    for (int i=0; i<6; i++) {
        cout << "ASCII VALUE ";
        char c = charArray1[i];
        cout << ((int)c);
        cout << "\n";
    }

    cout << "Now use easy notation\n";

    const char* charArray2 = "Hello";
    for (int i=0; i<6; i++) {
        cout << "ASCII VALUE ";
        char c = charArray2[i];
        cout << ((int)c);
        cout << "\n";
    }
}

int computeLengthOfString( const char* s ) {
    int length = 0;
    while ((*s)!=0) {
        s++;
        length++;
    }
    return length;
}

void testComputeLengthOfString() {
    const char* quotation="To be or not to be";
    int l1 = computeLengthOfString( quotation );
    int l2 = strlen( quotation ); // built in
    ASSERT( l1==l2 );
}

class IntArray {
public:
    int* firstElement;
    int  length;
};

class FastString {
public:
    char* firstElement;
    int   length;
};

/*  Let's create an example class */
class Pair {
public:
    double x;
    double y;
    Pair();
    Pair( double x, double y );
};

Pair::Pair() :
    x(0.0), y(0.0) {
}

Pair::Pair( double x, double y ) :
    x(x), y(y) {
}


void testNewPairArray() {
    int n = 5;
    Pair* myPairs = new Pair[n];
    for (int i=0; i<n; i++) {
        double xValue = myPairs[i].x;
        double yValue = myPairs[i].y;

        cout<<"Pair (";
        cout<< xValue;
        cout<<",";
        cout<< yValue;
        cout<<")\n";
    }
    delete[] myPairs;
}

char* thisFunctionReturnsAnArray() {
    /* This produces a compiler warning */
    char text[] = "Don't do this";
    return text;
}

void someOtherFunction() {
    char text[] = "Alternative text\n";
    cout << text;
    cout << "\n";
}

void testDontReturnArrays() {
    char* text = thisFunctionReturnsAnArray();
    someOtherFunction();
    cout << text;
    cout << "\n";
}


char* thisFunctionReturnsAPointer() {
    char text[] = "This works";
    int n = strlen(text);
    char* ret = new char[n+1];
    /* We now get a compiler warning here */
    strcpy( ret, text );
    return ret;
}

void testReturnPointerJustAboutOK() {
    char* text = thisFunctionReturnsAPointer();
    someOtherFunction();
    cout << text;
    cout << "\n";
    // don't forget to free the memory
    delete[] text;
}


void testCreateObjectOnHeap() {

    Pair* myPair = new Pair;
    myPair->x = 1.3;
    myPair->y = 2.5;

    cout << "Pair (";
    cout << (myPair->x);
    cout << ", ";
    cout << (myPair->y);
    cout << ")\n";

    delete myPair;
}

void testUsingStarOperator() {

    Pair* myPair = new Pair;
    Pair& pairRef=*myPair;

    pairRef.x = 1.3;
    pairRef.y = 2.5;

    cout << "Pair (";
    cout << (pairRef.x);
    cout << ", ";
    cout << (pairRef.y);
    cout << ")\n";

    cout << "Pair (";
    cout << ((*myPair).x);
    cout << ", ";
    cout << ((*myPair).y);
    cout << ")\n";

    delete myPair;
}

void testUsingSharedPtr() {

    shared_ptr<Pair> myPair = make_shared<Pair>();
    Pair& pairRef=*myPair;

    pairRef.x = 1.3;
    pairRef.y = 2.5;

    cout << "Pair (";
    cout << (pairRef.x);
    cout << ", ";
    cout << (pairRef.y);
    cout << ")\n";

    cout << "Pair (";
    cout << ((*myPair).x);
    cout << ", ";
    cout << ((*myPair).y);
    cout << ")\n";

    //delete myPoint;
}

shared_ptr<Pair> thisFunctionReturnsASharedPointer() {
    shared_ptr<Pair> pair = make_shared<Pair>();
    pair->x = 1.3;
    pair->y = 2.5;
    return pair;
}

void testReturnSharedPointer() {

    shared_ptr<Pair> p =
        thisFunctionReturnsASharedPointer();

    cout <<"Pair (";
    cout << p->x;
    cout << ", ";
    cout << p->y;
    cout << ")\n";

    // no need to delete (phew!)
}

void testOverrunning() {
    char* shortText = new char[20];
    for (int i=0; i<1000; i++) {
        shortText[i] = 'x';
    }
    delete[] shortText;
}
void testIncorrectMemoryManagement() {
    int* a = new int[10];
    int* b = new int[20000000];
    cout << "Arrays created";
    delete[] a;
    delete[] b;
}

void testCorrectMemoryManagement() {
    bool errorOccurred = false;
    int* a = new int[10];
    try {
        int* b = new int[20000000];
        try {
            cout << "Arrays created";
        } catch (...) {
            errorOccurred = true;
        }
        delete[] b;
    } catch (...) {
        errorOccurred = true;
    }
    delete[] a;
    if (errorOccurred) {
        throw exception();
    }
}

void testArrowOperator() {
    Pair p;
    Pair* pointerToP = &p;

    // Use -> to access fields via a pointer
    pointerToP->x = 123.0;
    pointerToP->y = 456.0;

    // We check that c has changed
    ASSERT( p.x==123.0 );
    ASSERT( p.y==456.0 );

    // You could use * and .
    ASSERT( (*pointerToP).x==123.0 );
    ASSERT( (*pointerToP).y==456.0 );

}

class Instrument {
public:
    string bloombergTicker;
    string ricCode;
    string companyName;
    Instrument() {}
};

class Position {
public:
    string trader;
    double quantity;
    Instrument* instrument;
    explicit Position( Instrument * instrument );
};

Position::Position( Instrument* instrument ) :
    instrument( instrument ) {
}

vector<Position> constructPositions() {
    // the caller of this function
    // should call delete on the instrument
    // when they are done with all the positions
    vector<Position> positions;

    Instrument* instrument = new Instrument;
    instrument->companyName = "Google";
    instrument->bloombergTicker = "GOOG US Equity";
    instrument->ricCode = "GOOG.OQ";

    Position p1(instrument);
    p1.trader = "Han";
    p1.quantity = 100.00;
    positions.push_back( p1 );

    Position p2(instrument);
    p2.trader = "Leia";
    p2.quantity = -100.00;
    p2.instrument = instrument;
    positions.push_back( p2 );

    return positions;
}

void testConstructPositions() {
    vector<Position> r = constructPositions();
    int n = r.size();
    for (int i=0; i<n; i++) {
        cout << "Position "<<i<<"\n";
        Position& p=r[i];
        cout << "Trader "<<p.trader<<"\n";
        cout << "Quantity "<<p.quantity<<"\n";
        cout << "Instrument ";
        cout << p.instrument->companyName<<"\n";
        cout << "\n";
    }
    delete r[0].instrument;
}
string getCompanyName( Position& position ) {
    if (position.instrument==nullptr) {
        return "Name not set";
    } else {
        return position.instrument->companyName;
    }
}

class PositionV2 {
public:
    string trader;
    double quantity;
    shared_ptr<Instrument> instrument;
    explicit PositionV2(shared_ptr<Instrument> ins );
};

PositionV2::PositionV2(shared_ptr<Instrument> ins ) :
    instrument( ins ) {
}

vector<PositionV2> constructPositionsV2() {
    vector<PositionV2> positions;

	shared_ptr<Instrument> ins
		= make_shared<Instrument>();
    ins->companyName = "Google";
    ins->bloombergTicker = "GOOG US Equity";
    ins->ricCode = "GOOG.OQ";

    PositionV2 p1(ins);
    p1.trader = "Han";
    p1.quantity = 100.00;
    positions.push_back( p1 );

    PositionV2 p2(ins);
    p2.trader = "Leia";
    p2.quantity = -100.00;
    p2.instrument = ins;
    positions.push_back( p2 );

    return positions;
}


void testConstructPositionsV2() {
    vector<PositionV2> r = constructPositionsV2();
    int n = r.size();
    for (int i=0; i<n; i++) {
        cout << "Position "<<i<<"\n";
        PositionV2& p=r[i];
        cout << "Trader "<<p.trader<<"\n";
        cout << "Quantity "<<p.quantity<<"\n";
        cout << "Instrument ";
        cout << p.instrument->companyName<<"\n";
        cout << "\n";
    }
}

class PositionV3 {
public:
    string trader;
    double quantity;
    Instrument& instrument;
    explicit PositionV3( Instrument& instrument );
};

PositionV3::PositionV3( Instrument& instrument ) :
    instrument(instrument) {
}

PositionV3 constructPositionV3() {
    // This function doesn't work, the instrument
    // is deleted, so all the returned positions
	// contain broken references
    vector<PositionV3> positions;

    Instrument instrument;
    instrument.companyName = "Google";
    instrument.bloombergTicker = "GOOG US Equity";
    instrument.ricCode = "GOOG.OQ";

    PositionV3 position(instrument);
    position.trader = "Han";
    position.quantity = 100.00;
    return position;
}
void testConstructPositionV3() {
    // This will fail horribly
    PositionV3 p = constructPositionV3();
    cout << "Trader "<<p.trader<<"\n";
    cout << "Quantity "<<p.quantity<<"\n";
    cout << "Instrument ";
    cout << p.instrument.companyName<<"\n";
    cout << "\n";
}

class RealFunction {
public:
    ~RealFunction() {};
    virtual double evaluate( double x )=0;
};

double integral( RealFunction& f, double a, double b, int nSteps ) {
    double h = (b-a)/nSteps;
    double s = a + h/2;
    double total = 0;
    for (int i=0; i<nSteps; i++) {
        total+=h*f.evaluate(s);
        s+=h;
    }
    return total;
}

double integralToInfinity(RealFunction& f,
	double lowerLimit, int nPoints) {

    class DefiniteIntegrand : public RealFunction {
    public:
        RealFunction& g;
        double lowerLimit;

        DefiniteIntegrand(RealFunction& g,
                          double lowerLimit) :
            g(g), lowerLimit(lowerLimit) {
        }

        double evaluate(double x) {
            return (1/(x*x))
                * g.evaluate(lowerLimit - 1 + (1/x));
        }
    };

    DefiniteIntegrand integrand(f, lowerLimit);
    return integral(integrand, 0, 1, nPoints);
}
double cStyleIntegrate( double (*f)(double),
                        double a, double b,
                        int nSteps  ) {
    double h = (b-a)/nSteps;
    double s = a + h/2;
    double total = 0;
    for (int i=0; i<nSteps; i++) {
        total+=h*f(s);
        s+=h;
    }
    return total;
}
void testCStyleIntegrate() {
  double value = cStyleIntegrate( &sin, 0, 1, 1000);
  ASSERT_APPROX_EQUAL(value,-cos(1.0)+cos(0.0),0.0001);
}

/**
 *  A void* points to potentially any data,
 *  A void** is an array of pointers of unspecified type
 *  This will reverse the order of such an array
 */
void reverse( void* memArray,
              int length,
              size_t sizeOfElement ) {
    char* asChar = (char*)memArray;
    char* temp = new char[length*sizeOfElement];
    memcpy( temp, memArray, length*sizeOfElement );
    for (int i=0; i<length; i++) {
        memcpy( asChar + i*sizeOfElement,
                temp + (length-i-1)*sizeOfElement,
                sizeOfElement );
    }
    delete[] temp;
}

void testReverse() {
    char* s1 = "The rain in Spain";
    char* s2 = "falls mainly in";
    char* s3 = "the plains";
    char* sArray[] = {s1,s2,s3};
    reverse( sArray, 3, sizeof(char*) );
    for (int i=0; i<3; i++) {
        cout << sArray[i] << "\n";
    }

    double dArray[] = {1.0, 2.0, 3.0};
    reverse( dArray, 3, sizeof( double ));
    for (int i=0; i<3; i++) {
        cout << dArray[i] << "\n";
    }
}

void polarToCartesian(double r, double theta,
	double* x, double* y) {
	*x = r*cos(theta);
	*y = r*sin(theta);
}

void testPolarToCartesian() {
	double r = 2;
	double theta = atan(1);
	double x;
	double y;
	polarToCartesian(r, theta, &x, &y);
	ASSERT_APPROX_EQUAL(x, sqrt(2), 0.0001);
	ASSERT_APPROX_EQUAL(y, sqrt(2), 0.0001);
}



void constPointerExamples() {
	const char* ptr = "A string";
	ptr++;
	std::cout << (*ptr);
	// (*ptr)='a';  // You can't change the data
	// using a const char*

	char* fiveChars = new char[5];
	char *const constPtr = fiveChars;
	// constPtr++;  // You can't change a char *const
	(*constPtr) = 'h'; // but you can change
	                   // what it points to
}
void fivePrimes() {
	int* fivePrimes = new int[5];
	fivePrimes[0] = 2;
	fivePrimes[1] = 3;
	fivePrimes[2] = 5;
	fivePrimes[3] = 7;
	fivePrimes[4] = 11;
}


int main() {
    TEST( testUninitialisedArray );
    TEST( testInitialisedArray );
    TEST( testInitialisedWithZeroArray );
    TEST( testArrayLengthBiggerThanData );
    TEST( test2DArray );
    TEST( testUsingAnArray );
    TEST( testVariableSizeData );
    TEST( testPointerExample );
    TEST( testUsingPointers );
    TEST( testCharArray );
    TEST( testComputeLengthOfString );
    TEST( testNewPairArray );
    TEST( testReturnPointerJustAboutOK );
    TEST( testCreateObjectOnHeap );
    TEST( testUsingStarOperator );
    TEST( testCorrectMemoryManagement );
    TEST( testArrowOperator );
    TEST( testConstructPositions );
    TEST( testConstructPositionsV2 );
    TEST( testCStyleIntegrate );
    TEST( testReverse );
	TEST(testPolarToCartesian);

    //TEST( testDontReturnArrays );
    //TEST( testOverrunning );
    //TEST( testConstructPositionV3 );


    return 0;
}