void *run_thread4( void *ptr ) {
    struct car *data = (struct car*) ptr;
    pthread_t id = pthread_self();
    int size1 = col/4;
    int size2 = col/2;
    int size3 = size1+size2;

    //int size2 = col - size1;
    int flag;

    if(pthread_equal(id,tId[0])) {
        bubbleSortYearAndMake(data, 0, size1);
        writeInFile("test1.txt", data, 0, size1);
    } else if (pthread_equal(id,tId[1])){
        bubbleSortYearAndMake(data, size1, size2);
        writeInFile("test2.txt", data, size1, size2);
    } else if (pthread_equal(id,tId[2])){
        bubbleSortYearAndMake(data, size2, size3);
        writeInFile("test3.txt", data, size2, size3);
    } else{
        bubbleSortYearAndMake(data, size3, col);
        writeInFile("test4.txt", data, size3, col);
    }
    pthread_exit(NULL);
}
int main ()
{
	testResult_t *result = initializeTestResult();

	getFS();	

	deleteFile("File to Delete");
	deleteDir("Dir to Delete");

	int newFd = openFile("NewFile");

	char *text = "Here is some text.";
	int writeLen = writeInFile(newFd, text, strlen(text));
	assert(writeLen == strlen(text), "File write return value test.", result);
	seekInFile(newFd, 0);
	char target[100];
	memset(target, 0, sizeof(target));
	int readLen = readInFile(newFd, target, strlen(text));
	assert(readLen == strlen(text), "File write return value test.", result);
	deny(strcmp(target, text), "Read + write test.", result);

	int fd = openFile("File to Delete");

	seekInFile(newFd, FILE_BLOCK_DATA_SIZE - 2);
	writeLen = writeInFile(newFd, text, strlen(text));
	seekInFile(newFd, FILE_BLOCK_DATA_SIZE - 2);
	readLen = readInFile(newFd, target, strlen(text));
	assert(readLen == strlen(text), "Non-contiguous allocation read+write test.", result);
	deny(strcmp(target, text), "Read + write test.", result);

	mkDir("Dir to Delete");

	giveDirListing();

	deleteFile("File to Delete");
	mkDir("NewDir");
	giveDirListing();

	deleteDir("Dir to Delete");

	giveDirListing();

	seekInFile(newFd, 0);

	int i;
	for (i = 0; i < 150; i++)
	{
		writeInFile(newFd, text, strlen(text));
		seekInFile(newFd, (i * FILE_BLOCK_DATA_SIZE) - 2);
	}

	printTestResult(result);
	freeTestResult(result);
	return 0;
}
void *run_thread10( void *ptr ) {
    struct car *data = (struct car*) ptr;
    pthread_t id = pthread_self();
    int size1 = col/10;//10612
    int size2 = size1+size1;//21224
    int size3 = size2+size1;//31836
    int size4 = size3+size1;//42449
    int size5 = size4+size1;//53062
    int size6 = size5+size1;// 63674
    int size7 = size6+size1; //74286
    int size8 = size7+size1; // 84899
    int size9 = size8+size1; //95512
    int size10 = size9+size1; //106125

    if(pthread_equal(id,tID[0])) {
        bubbleSortYearAndMake(data, 0, size1);
        writeInFile("test1.txt", data, 0, size1);
    } else if (pthread_equal(id,tID[1])){
        bubbleSortYearAndMake(data, size1, size2);
        writeInFile("test2.txt", data, size1, size2);
    } else if (pthread_equal(id,tID[2])){
        bubbleSortYearAndMake(data, size2, size3);
        writeInFile("test3.txt", data, size2, size3);
    } else if (pthread_equal(id,tID[3])){
        bubbleSortYearAndMake(data, size3, size4);
        writeInFile("test4.txt", data, size3, size4);
    } else if (pthread_equal(id,tID[4])){
        bubbleSortYearAndMake(data, size4, size5);
        writeInFile("test5.txt", data, size4, size5);
    } else if (pthread_equal(id,tID[5])){
        bubbleSortYearAndMake(data, size5, size6);
        writeInFile("test6.txt", data, size5, size6);
    } else if (pthread_equal(id,tID[6])){
        bubbleSortYearAndMake(data, size6, size7);
        writeInFile("test7.txt", data, size6, size7);
    } else if (pthread_equal(id,tID[7])){
        bubbleSortYearAndMake(data, size7, size8);
        writeInFile("test8.txt", data, size7, size8);
    } else if (pthread_equal(id,tID[8])){
        bubbleSortYearAndMake(data, size8, size9);
        writeInFile("test9.txt", data, size8, size9);
    } else {
        bubbleSortYearAndMake(data, size9, col);
        writeInFile("test10.txt", data, size9, col);
    }
    pthread_exit(NULL);
}
void *run_thread2( void *ptr ) {
    struct car *data = (struct car*) ptr;
    pthread_t id = pthread_self();
    int size1 = col/2;
    int size2 = col - size1;
    int flag;

    if(pthread_equal(id,tid[0])) {
        bubbleSortYearAndMake(data, 0, size1);
        writeInFile("test1.txt", data, 0, size1);
    } else {
        bubbleSortYearAndMake(data, size2, col);
        writeInFile("test2.txt", data, size2, col);
    }

    pthread_exit(NULL);
}
void *run_thread1( void *ptr ) {
    struct car *data = (struct car*) ptr;

    bubbleSortYearAndMake(data, 0, col);
    writeInFile("test1.txt",data,0,col);

    pthread_exit(NULL);
}
int main(int argc, char* argv[])
{
	std::vector<Mat<float> > mse;
	
	//Neural Networks settings :
	Topology topo;
	unsigned int nbrneurons = 25;
	unsigned int nbrlayer = 1;
	unsigned int nbrinput = width*height;
	unsigned int nbroutput = 10;
	
	//topo.push_back(nbrinput,NTNONE);	//input layer
	topo.push_back(nbrinput,NTSIGMOID);	//input layer
	
	//topo.push_back(nbrneurons, NTSIGMOID);
	topo.push_back(15, NTSIGMOID);
	
	//topo.push_back(nbroutput, NTSOFTMAX);	//linear output
	topo.push_back(nbroutput, NTSIGMOID);	//linear output
	
	NN<float> nn(topo);
	nn.learning = false;
	//------------------------------
	
	//DATASET SETTINGS :
	report.open(report_fn.c_str(), ios::out);
    image.open(training_image_fn.c_str(), ios::in | ios::binary); // Binary image file
    label.open(training_label_fn.c_str(), ios::in | ios::binary ); // Binary label file

	// Reading file headers
    char number;
    for (int i = 1; i <= 16; ++i) {
        image.read(&number, sizeof(char));
	}
    for (int i = 1; i <= 8; ++i) {
        label.read(&number, sizeof(char));
	}
	
	//------------------------------
	
	//checking rotation :
	Mat<float> im1(8,8, (char)1);
	Mat<float> im2( rotate(im1,PI/2.0f) );
	
	im1.afficher();
	im2.afficher();
	//--------------------------------
	
	//checking arctan !!!
	float y = -4.0f;
	float x = 4.0f;
	std::cout << arctan(y,x)*180.0f/(PI) << std::endl;
	//--------------------------------------------------
	
	//checking reading :
	char labelval = 0;
	float theta = PI/2;
	im1 = inputMNIST(labelval);
	im2 = rotate(im1,theta);
	im2.afficher();
		
	std::cout << "Rotation of : " << theta*180.0f/PI << std::endl;
	//---------------------------------------------------
	
	
	
	int iteration = 25000;
	int offx = 2;
	int offy = 2;
	int size = 28;
	int countSuccess = 0;
	
	while( iteration)
	{
		Mat<float> rotatedinput( inputMNIST(labelval) );
		//let us choose the rotation :
		float theta = ((float)(rand()%360))*PI/180.0f;
		
		//let us apply it :
		rotatedinput = extract( rotate(rotatedinput, theta), offx,offy, offx+(size-1), offy+(size-1) );
		
		Mat<float> input( reshapeV( rotatedinput ) );
		Mat<float> target( 0.0f, 10,1);
		target.set( 1.0f, labelval+1, 1);
		
		if(labelval < 9)
		{
			Mat<float> output( nn.feedForward( input) );
	
			int idmax = idmin( (-1.0f)*output).get(1,1);
	
			transpose( operatorL(target,output) ).afficher();
	
			std::cout << " LEARNING ITERATION : " << iteration << " ; IDMAX = " << idmax << std::endl;
	
	
			nn.backProp(target);
			//nn.backPropCrossEntropy(target);
			
			
			//counting :
			if(idmax == labelval+1)
			{
				countSuccess++;
			}
			
			//-------------------
			
			if( iteration % 1000 == 0)
			{
				std::cout << " TEST : " << countSuccess << " / " << 1000 << std::endl;
				mse.push_back(Mat<float>((float)countSuccess,1,1));
		
				writeInFile(std::string("./mse.txt"), mse);
		
				countSuccess = 0;
			}
			
			iteration--;
			
			
		}
		
		
		
	}
	
	std::cout << " VALIDATION TEST : in progress.." << std::endl;
	
	iteration = 1000;
	int success = 0;
	while( iteration)
	{
		Mat<float> rotatedinput( inputMNIST(labelval) );
		//let us choose the rotation :
		//float theta = rand()%360;
		float theta = ((float)(rand()%360))*PI/180.0f;
		
		//let us apply it :
		rotatedinput = extract( rotate(rotatedinput, theta), offx,offy, offx+(size-1), offy+(size-1) );
		
		Mat<float> input( reshapeV( rotatedinput ) );
		Mat<float> target( 0.0f, 10,1);
		target.set( 1.0f, labelval+1, 1);
		
		if(labelval < 5)
		{
			Mat<float> output( nn.feedForward( input));
			int idmax = idmin( (-1.0f)*output).get(1,1);
		
			transpose(output).afficher();
			std::cout << " ITERATION : " << iteration << " ; IDMAX = " << idmax << std::endl;
		
			if(idmax == labelval+1)
			{
				success++;
			}
			
			iteration--;
		}
		
	}
	
	std::cout << "VALIDATION TEST : " << success << " / 1000." << std::endl;
	
	report.close();
	label.close();
	image.close();
	
	nn.save(std::string("neuralnetworksDIGITROTATED"));
		
	return 0;
}
int main(void) {
    FILE* fp;
    FILE* f;
    int pid;
    clock_t time;
    int size, size1, size2, size3, size4, size5, size6, size7, size8, size9, size10;
    char fileName1[] = "FLAT_RCL.txt";
    char buffer[10000];
    struct car c[col];
    int center;
    int structCount = 0,count = 0, i = 0, unsorted, choice;
    if( (fp = fopen(fileName1, "r")) == NULL ) {
        printf("unable to open %s for reading\n", fileName1);
        exit(1);
    }

    while( fgets(buffer, sizeof(buffer), fp) != NULL ) {
        c[structCount] = getValues(buffer);
        structCount++;
    }
    fclose( fp );


   /* if( (f = fopen(fileName2, "w")) == NULL ) {
        printf("unable to open %s\n", fileName2);
        exit(1);
    }*/

    printf("0 for 1 process, 1 for 2 processes, 2 for 4 processes & 3 for 10 processes!\n");
    printf("Enter 0,1,2 or 3  to choose an operation:\n");
    scanf("%d",&choice);
    int flag = choice;
    while(choice<4) {
        if(choice==0) {
            choice = 4;
            time=clock();
            bubbleSortYearAndMake(c, 0, structCount);
            writeInFile("test1.txt",c,0,structCount);


        } else if( choice == 1 ) {
            choice = 4;
            size = structCount/2;
            count = structCount;
            //printf("size =  %d\n", size);
            time=clock();
            pid = fork();

            if(pid==0) {
                bubbleSortYearAndMake(c, 0, size);
                writeInFile("test1.txt",c,0,size);
            } else {
                bubbleSortYearAndMake(c, size, count);
                writeInFile("test2.txt",c,size,count);
                return 0;
            }

        } else if (choice == 2)/* choice 2: for 4 processes */{
            choice = 4;
            size1 = structCount/4;
            size2 = structCount/2;
            size3 = (structCount/4) * 3;
            time=clock();
            pid=fork();
            if(pid==0) {
                pid = fork();
                if(pid == 0) {
                    bubbleSortYearAndMake(c, 0, size1);
                    writeInFile("test1.txt",c,0,size1);
                } else {
                    bubbleSortYearAndMake(c,size1,size2);
                    writeInFile("test2.txt",c,size1,size2);
                    return 0;
                }
            } else {
                pid=fork();
                if(pid==0) {
                    bubbleSortYearAndMake(c, size2, size3);
                    writeInFile("test3.txt",c,size2,size3);
                    return 0;
                } else {
                    bubbleSortYearAndMake(c, size3, structCount);
                    writeInFile("test4.txt",c,size3,structCount);
                    return 0;
                }

            }


        } else {
            count = structCount;
            choice = 4;
            size1 = structCount/10;
            //printf("size1 = %d\n", size1);
            size2 = (count * 2)/10;
            //printf("size2 = %d\n", size2);
            size3 = (count * 3)/10;
            //printf("size3 = %d\n", size3);
            size4 = (count * 4)/10;
            //printf("size4 = %d\n", size4);
            size5 = (count * 5)/10;
            //printf("size5 = %d\n", size5);
            size6 = (count * 6)/10;
            //printf("size6 = %d\n", size6);
            size7 = (count * 7)/10;
            //printf("size7 = %d\n", size7);
            size8 = (count * 8)/10;
            //printf("size8 = %d\n", size8);
            size9 = (count * 9)/10;
            //printf("size9 = %d\n", size9);
            size10 = (count * 10)/10;
            //printf("size10 = %d\n", size10);
            time=clock();
            pid = fork();
            if(pid==0) {
                pid = fork();
                if(pid==0) {
                    bubbleSortYearAndMake(c, 0, size1);
                    writeInFile("test1.txt",c,0,size1);
                    return 0;
                } else {
                    pid = fork();
                    if(pid==0) {
                        bubbleSortYearAndMake(c, size1, size2);
                        writeInFile("test2.txt",c,size1, size2);
                        return 0;
                    } else {
                        pid = fork();
                        if(pid==0) {
                            bubbleSortYearAndMake(c, size2, size3);
                            writeInFile("test3.txt",c,size2, size3);
                            return 0;
                        } else {
                            pid = fork();
                            if(pid==0) {
                                bubbleSortYearAndMake(c, size3, size4);
                                writeInFile("test4.txt",c,size3, size4);
                                return 0;
                            } else {
                                bubbleSortYearAndMake(c, size4, size5);
                            writeInFile("test5.txt",c,size4, size5);
                                return 0;
                            }
                        }
                    }
                }
            } else {
                pid = fork();

                if(pid==0) {
                    bubbleSortYearAndMake(c, size5, size6);
                    writeInFile("test6.txt",c,size5, size6);
                } else {
                    pid = fork();
                    if(pid==0) {
                        bubbleSortYearAndMake(c, size6, size7);
                        writeInFile("test7.txt",c,size6, size7);
                        return 0;
                    } else {
                        pid = fork();
                        if(pid==0) {
                            bubbleSortYearAndMake(c, size7, size8);
                            writeInFile("test8.txt",c,size7, size8);
                            return 0;
                        } else {
                            pid = fork();
                            if(pid==0) {
                                bubbleSortYearAndMake(c, size8, size9);
                                writeInFile("test9.txt",c,size8, size9);
                                return 0;
                            } else {
                                bubbleSortYearAndMake(c, size9, size10);
                                writeInFile("test10.txt",c,size9, size10);
                                return 0;
                            }
                        }
                    }
                }
            }


           /* time=clock()- time;
            printf("time taken to do sorting using 10 processes concurrently is %f",(float)time/CLOCKS_PER_SEC);*/
        }

    }

    while(1){
        if(flag == 1) {

            time=clock() - time;
            printf("time taken to do sorting using 2 process is %f\n",(float)time/CLOCKS_PER_SEC);
            break;
            readAndMerge("test1.txt","test2.txt","merge1.txt",size,size);


        } else if(flag==2) {

            time=clock()- time;
            printf("time taken to do sorting using 4 process is %f",(float)time/CLOCKS_PER_SEC);
            break;
            readAndMerge("test1.txt", "test2.txt", "merge1.txt", 25000, 25000);
            readAndMerge("test3.txt", "test4.txt", "merge2.txt", 25000, 25000);
            readAndMerge("merge1.txt","merge2.txt","final.txt",50000,50000);
        } else {

            time=clock()- time;
            printf("time taken to do sorting using 10 processes concurrently is %f",(float)time/CLOCKS_PER_SEC);
            break;
            /*
            readAndMerge("test1.txt", "test2.txt", "merge1.txt", 10000, 10000);
            readAndMerge("test3.txt", "test4.txt", "merge2.txt", 10000, 10000);
            readAndMerge("test5.txt", "test6.txt", "merge3.txt", 10000,10000);
            readAndMerge("test7.txt", "test8.txt", "merge4.txt", 10000,10000);
            readAndMerge("test9.txt", "test10.txt", "merge5.txt", 10000,10000);

            readAndMerge("merge1.txt", "merge2.txt", "merge1.txt", 20000,20000);
            readAndMerge("merge3.txt", "merge4.txt", "merge2.txt", 20000, 20000);

            readAndMerge("merge1.txt", "merge2.txt", "merge1.txt", 40000, 40000);

            readAndMerge("merge1.txt", "merge5.txt", "final.txt", 80000, 20000);*/
        }
        //bubbleSortYearAndMake(c, structCount);
    }
   /* printf("----------------------------\n");
    for(i = 0; i < structCount; i++) {
        fprintf(f,"%d    %s\n", c[i].year ,c[i].make);

    }*/

    return 0;
}