123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911 |
- //Stephen Stengel
- //hpc lab1 header file
- #ifndef STEPHEN_STENGEL_LAB1
- #define STEPHEN_STENGEL_LAB1
- #include <stdio.h>
- #include <stdlib.h> //exit(), malloc()
- #include <string.h> //strcmp()
- #include <time.h> //time()
- #include <limits.h> //INT_MAX
- #include <math.h> //math functions
- #include <ctype.h> //isspace(), isdigit(), etc.
- //~ #include <stdbool.h> //bool type
- #include <unistd.h> //access() check file exists.
- #define TRUE 1
- #define FALSE 0
- //These are a bit higher than what runs in a reasonable time. 100/10 is about an hour.
- #define GLOBAL_MAX_M 125
- #define GLOBAL_MAX_N 12
- #define RAND_MULT 1000
- #define MAX_COMMAND_LEN 2000
- #define HELP_TEXT_PATH "helpfile"
- struct node
- {
- double value;
- int row;
- int col;
- struct node *right;
- struct node *down;
- };
- //Helper functions
- int checkForHelpCommands(int argc, char** argv);
- _Bool strIsHelp(char* aString);
- void printTextFile(char* inputPath);
- int* generateArray(int mySize, int* outArray);
- int printIntArray(int* array, int length);
- double getElapsedTime(struct timespec start, struct timespec finish);
- _Bool isInputTwoNumbers(int argc, char **argv);
- int checkInput(int argc, char **argv);
- double doubleRand(double low, double high);
- double** createSquareArray(int size);
- double** fillSquareArrayRandomDoubles(double** myArray, int size);
- int freeSquareDoubleArray(double** myArray, int size);
- double** copySquareDoubleArray(double** myArray, int size);
- _Bool isStringAllDigits(char* myString);
- void printSquareDoubleArray(double **myArray, int size);
- double** createIdentityMatrix(int size);
- int testFunctions();
- void printListValues(struct node* head);
- int getListSize(struct node* head);
- struct node* copyNode(struct node* myNode);
- void freeList(struct node* head);
- //stuff
- int runArrayTests(int maxM, int maxN);
- int powerArrays(double **myArray, int sizeM, int N);
- double **multSquareArrays(double **original, double **intermediate, double **output, int size);
- int printArrayDataPoint(int M, int N, int i, int j, double time);
- int deleteFileIfExists(char * myFilename);
- int runListTests(int maxM, int maxN);
- struct node* createList(int size);
- struct node* nodeAlloc();
- void printNodeValues(struct node* myNode);
- struct node* constructNode();
- struct node* multTwoSquareLists(struct node* A, struct node* B);
- double** fillArrayWithListVals(struct node* head);
- struct node* advanceNode(struct node* myNode, int row, int col);
- struct node* zeroAList(struct node* myList);
- int listDemo(int M, int N);
- struct node* powerLists(struct node* myList, int sizeThisRound, int ennThisRound);
- struct node* copyList(struct node* myList);
- int printListDataPoint(int maxM, int maxN, int size, int ennThisRound, double lowest);
- _Bool isInputThreeNumbers(int argc, char **argv);
- int testFunctions()
- {
- int testSize = 3;
- double **myArray = createSquareArray(testSize);
- myArray = fillSquareArrayRandomDoubles(myArray, testSize);
- printSquareDoubleArray(myArray, testSize);
- double** identity = createIdentityMatrix(testSize);
- printSquareDoubleArray(identity, testSize);
-
- printf("first times identity...\n");
- double **output = createSquareArray(testSize);
- output = multSquareArrays(identity, myArray, output, testSize);
- printSquareDoubleArray(output, testSize);
-
- freeSquareDoubleArray(myArray, testSize);
- freeSquareDoubleArray(identity, testSize);
- freeSquareDoubleArray(output, testSize);
- return 0;
- }
- //Creates identity matrix of given size. Malloc inide. free outside.
- double** createIdentityMatrix(int size)
- {
- double** myArray = (double**)malloc( sizeof(double*) * size );
- for (int i = 0; i < size; i++)
- {
- //calloc( #elements, size in bytes), sets all to zero.
- myArray[i] = (double*)calloc( size, sizeof(double) );
- myArray[i][i] = 1;
- }
-
- return myArray;
- }
- //listMalloc inside, freeList outside
- struct node* createIdentityList(int size)
- {
- struct node* myList = createList(size);
-
- struct node* i = myList;
-
- while (i != NULL)
- {
- struct node* j = i;
- while (j != NULL)
- {
- if (j->row == j->col)
- {
- j->value = 1;
- }
- else
- {
- j->value = 0;
- }
- j = j->right;
- }
- i = i->down;
- }
-
- return myList;
- }
- struct node* zeroAList(struct node* myList)
- {
- struct node* i = myList;
-
- while (i != NULL)
- {
- struct node* j = i;
- while (j != NULL)
- {
- j->value = 0;
- j = j->right;
- }
- i = i->down;
- }
-
- return myList;
- }
- int listDemo(int M, int N)
- {
- //
- int size = M;
- struct node* head = createList(size);
- freeList(head);
-
- struct node* A = createList(size);
- struct node* B = createList(size);
- //~ struct node* B = createIdentityList(size); //to see if it works!
- struct node* output = multTwoSquareLists(A, B);
-
- freeList(A);
- freeList(B);
- freeList(output);
-
- return 0;
- }
- int runListTests(int maxM, int maxN)
- {
- //~ listDemo(maxM, maxN);
-
- struct timespec start, finish;
- double lowest = INT_MAX;
- double elapsedTime = -1;
-
- for (int i = 0; i < maxM; i++)
- {
- for (int j = 0; j < maxN; j++)
- {
- //~ int sizeThisRound = i;
- int ennThisRound = j;
-
- //do three tests timing each
- lowest = INT_MAX;
- for (int k = 0; k < 3; k++)
- {
- clock_gettime(CLOCK_MONOTONIC, &start);
-
- int size = i;
- struct node* A = createList(size);
- struct node* B = createList(size);
-
- for (int hey = 0; hey < ennThisRound - 1; hey++)
- {
- struct node* output = multTwoSquareLists(A, B);
- freeList(output);
- }
- elapsedTime = getElapsedTime(start, finish);
-
- freeList(A);
- freeList(B);
-
- //~ powerLists(myList, sizeThisRound, ennThisRound); //
- if (elapsedTime < lowest)
- {
- lowest = elapsedTime;
- }
-
- printListDataPoint(maxM, maxN, size, ennThisRound, lowest);
- }
- }
- }
-
- return 0;
- }
- int printListDataPoint(int M, int N, int i, int j, double time)
- {
- char dataFolder[] = "../data/";
- char dataBackupName[1000];
- sprintf(dataBackupName, "%slab1-CLISTSdata-M%d-N%d.txt", dataFolder, M, N);
-
-
- FILE *myFile = fopen(dataBackupName, "a");
- fprintf(myFile, "%d %d %f\n", i, j, time);
- fclose(myFile);
-
- return 0;
- }
- //creates intermediate with maloc( returns intermediate) free list outside.
- struct node* powerLists(struct node* myList, int size, int N)
- {
- printf("POWER LIST!\n");
- //~ struct node* original = copyList(myList);
- struct node* intermediate = copyList(myList);
- //~ intermediate = zeroAList(intermediate);
-
- for (int i = 1; i < N; i++)
- {
- struct node* output = createList(size);
- //~ output = multTwoSquareLists(original, intermediate);
- output = multTwoSquareLists(myList, myList);
- //copy output into intermediate
- intermediate = copyList(output);
-
- freeList(output);
- }
-
- printListValues(intermediate);
-
- //~ freeSquareDoubleArray(intermediate, sizeM);
- //~ freeSquareDoubleArray(originalCopy, sizeM);
-
-
- return myList;
- }
- struct node* copyList(struct node* myList)
- {
- //create an array to hold the nodes' addresses for linking.
- int size = getListSize(myList);
- struct node* reference[size][size];
-
- struct node* inode = myList;
-
- int i = 0;
- while (inode != NULL)
- {
- struct node* jnode = inode;
- int j = 0;
- while (jnode != NULL)
- {
- reference[i][j] = constructNode();
- reference[i][j]->row = i;
- reference[i][j]->col = j;
- reference[i][j]->value = jnode->value;
- jnode = jnode->right;
- }
- inode = inode->down;
- }
-
- //link nodes.
- for (i = 0; i < size; i++)
- {
- for (int j = 0; j < size; j++)
- {
- //there might be a more clever way to do this.
- if (i != size - 1)
- {
- reference[i][j]->down = reference[i+1][j];
- }
- if (j != size - 1)
- {
- reference[i][j]->right = reference[i][j+1];
- }
- }
- }
-
- struct node* head = reference[0][0];
-
- //~ printListValues(head);
-
- return head;
- }
- //Multiplies two SQUARE lists. Returns pointer to its head. Uses malloc.
- //free with freeList.
- struct node* multTwoSquareLists(struct node* A, struct node* B)
- {
- int size = getListSize(A);
- struct node* output = createList(size);
- output = zeroAList(output);
- //~ printf("print output after creation:\n");
- //~ printListValues(output);
- //~ double** aVectors = createSquareArray(size);
- //~ double** bVectors = createSquareArray(size);
-
- //fill vectors with values from lists in case I need them.
- //~ aVectors = fillArrayWithListVals(A);
- //~ bVectors = fillArrayWithListVals(B);
- struct node* tA = A;
- struct node* tB = B;
- struct node* tO = output;
- //~ int iCount = 0;
-
- //if current row/col wrong, advance.
- for (int i = 0; i < size; i++)
- {
- //reset heads each loop.
- tA = A;
- tB = B;
- tO = output;
- for (int j = 0; j < size; j++)
- {
- tA = A;
- tB = B;
- tO = output;
- tO = advanceNode(tO, i, j);
- for (int k = 0; k < size; k++)
- {
- //~ tA = A;
- //~ tB = B;
- tA = advanceNode(tA, i, k);
- tB = advanceNode(tB, k, j);
-
- tO->value += (tA->value * tB->value);
- }
- }
- }
-
- //~ printSquareDoubleArray(aVectors, size);
- //~ printSquareDoubleArray(bVectors, size);
- //~ printf("printing list output: \n");
- //~ printListValues(output);
-
- //~ //fill b vectors
-
- //~ //free stuff
- //~ freeSquareDoubleArray(aVectors, size);
- //~ freeSquareDoubleArray(bVectors, size);
-
- return output;
- }
- struct node* advanceNode(struct node* myNode, int row, int col)
- {
- while (myNode->row < row)
- {
- myNode = myNode->down;
- }
-
- while (myNode->col < col)
- {
- myNode = myNode->right;
- }
-
- return myNode;
- }
- void printListValues(struct node* head)
- {
- struct node* i = head;
-
- while (i != NULL)
- {
- struct node* j = i;
- while (j != NULL)
- {
- printf("%f", j->value);
- j = j->right;
- if (j)
- {
- printf("\t");
- }
- }
- printf("\n");
- i = i->down;
- }
- printf("\n");
- }
- //uses malloc.
- double** fillArrayWithListVals(struct node* head)
- {
- int size = getListSize(head);
- double** myArray = createSquareArray(size);
- struct node* i = head;
- int iCount = 0;
- while (i != NULL)
- {
- int jCount = 0;
- struct node* j = i;
- while (j != NULL)
- {
- myArray[iCount][jCount] = j->value;
- j = j->right;
- jCount++;
- }
- i = i->down;
- iCount++;
- }
- return myArray;
- }
- //creates the list, returns pointer to head. malloc used. must free.
- struct node* createList(int size)
- {
- //create an array to hold the nodes' addresses for linking.
- struct node* reference[size][size];
-
- //create nodes and fill with values.
- for (int i = 0; i < size; i++)
- {
- for (int j = 0; j < size; j++)
- {
- reference[i][j] = constructNode();
- reference[i][j]->row = i;
- reference[i][j]->col = j;
- //~ printNodeValues(reference[i][j]);
- }
- }
-
- //link nodes.
- for (int i = 0; i < size; i++)
- {
- for (int j = 0; j < size; j++)
- {
- //there might be a more clever way to do this.
- if (i != size - 1)
- {
- reference[i][j]->down = reference[i+1][j];
- }
- if (j != size - 1)
- {
- reference[i][j]->right = reference[i][j+1];
- }
- }
- }
-
- struct node* head = reference[0][0];
-
- //~ printListValues(head);
-
- return head;
- }
- void freeList(struct node* head)
- {
- struct node* currentRow = head;
- //~ int count = 0;
- while (currentRow != NULL)
- {
- struct node* currentCol = currentRow;
- while ( currentCol != NULL )
- {
- struct node* tmp = currentCol;
- currentCol = currentCol->right;
- //~ printf("value of thing being freed: %f\n", tmp->value);
- free(tmp);
- //~ count++;
- }
- currentRow = currentRow->down;
- }
- //~ printf("number of frees: %d\n", count);
- }
- //returns the size of the list as if it were a square array. size x size
- int getListSize(struct node* myNode)
- {
- struct node* tmp = myNode;
- int count = 0;
- while (tmp != NULL)
- {
- count++;
- tmp = tmp->right;
- }
-
- return count;
- }
- //creates and returns an elementwise copy of a node. uses malloc.
- struct node* copyNode(struct node* myNode)
- {
- struct node* copy = nodeAlloc();
- copy->col = myNode->col;
- copy->row = myNode->row;
- copy->right = myNode->right;
- copy->down = myNode->down;
- copy->value = myNode->value;
-
- return copy;
- }
- //Creates a node. Malloc inside.
- struct node* constructNode()
- {
- struct node* myNode = nodeAlloc();
- myNode->value = doubleRand(-1, 1) * RAND_MULT;
- myNode->row = -1;
- myNode->col = -1;
- myNode->right = NULL;
- myNode->down = NULL;
-
- return myNode;
- }
- void printNodeValues(struct node* N)
- {
- printf("\nNode %d,%d...\n", N->row, N->col);
- printf("This address: %p\n", N);
- printf("value: %f\n", N->value);
- printf("addr right: %p\taddr down: %p\n", N->right, N->down);
- }
- //mallocs space for a node. free outside.
- struct node* nodeAlloc()
- {
- return (struct node*)malloc( sizeof(struct node) );
- }
- int deleteFileIfExists(char * myFilename)
- {
- if ( access(myFilename, F_OK) == 0 )
- {
- //exists
- char command[MAX_COMMAND_LEN];
- sprintf(command, "rm %s", myFilename);
- printf("deleting file: %s\n", myFilename);
- system( command );
- }
- else
- {
- printf("could not find file: %s\n", myFilename);
- }
-
- return 0;
- }
- int runArrayTests(int maxM, int maxN)
- {
- //create timer variables.
- struct timespec start, finish;
- double lowest = INT_MAX;
- double elapsedTime = -1;
- for (int i = 1; i < maxM + 1; i++)
- {
- for (int j = 1; j < maxN + 1; j++)
- {
- //create array
- int sizeThisRound = i;
- int ennThisRound = j;
- double **myArray = createSquareArray(sizeThisRound);
- myArray = fillSquareArrayRandomDoubles(myArray, sizeThisRound);
-
- //do three tests timing each
- lowest = INT_MAX;
- for (int k = 0; k < 3; k++)
- {
- clock_gettime(CLOCK_MONOTONIC, &start);
- powerArrays(myArray, sizeThisRound, ennThisRound);
- elapsedTime = getElapsedTime(start, finish);
- if (elapsedTime < lowest)
- {
- lowest = elapsedTime;
- }
- }
- //append the i, j, time to a file
- printArrayDataPoint(maxM, maxN, sizeThisRound, ennThisRound, lowest);
-
- freeSquareDoubleArray(myArray, sizeThisRound);
- }
- }
-
-
- return 0;
- }
- int freeSquareDoubleArray(double** myArray, int size)
- {
- for (int i = 0; i < size; i++)
- {
- free(myArray[i]);
- }
- free(myArray);
-
- return 0;
- }
- //Creates square array. Returns pointer to it. Must free outside.
- double** createSquareArray(int size)
- {
- double **myArray = (double**)malloc( sizeof(double*) * size );
- for (int i = 0; i < size; i++)
- {
- myArray[i] = (double*)malloc( sizeof(double) * size );
- }
-
- return myArray;
- }
- //fills a square array with random double values.
- //returns pointer to array, lol
- double** fillSquareArrayRandomDoubles(double** myArray, int size)
- {
- for (int i = 0; i < size; i++)
- {
- for (int j = 0; j < size; j++)
- {
- myArray[i][j] = doubleRand(-1, 1) * RAND_MULT;
- }
- }
-
- return myArray;
- }
- //need to delete file at start of experiment if it exists.
- int printArrayDataPoint(int M, int N, int i, int j, double time)
- {
- //~ dataFolder = "../data/"
- //~ dataBackupName = f"lab1-data-M{maxSquareSize}-N{maxN}.txt"
- //~ dataBackupNamePath = dataFolder + dataBackupName
-
- char dataFolder[] = "../data/";
- char dataBackupName[1000];
- sprintf(dataBackupName, "%slab1-CARRAYdata-M%d-N%d.txt", dataFolder, M, N);
-
-
- FILE *myFile = fopen(dataBackupName, "a");
- fprintf(myFile, "%d %d %f\n", i, j, time);
- fclose(myFile);
-
- return 0;
- }
- int powerArrays(double **myArray, int sizeM, int N)
- {
- double **originalCopy = copySquareDoubleArray(myArray, sizeM);
- double **intermediate = copySquareDoubleArray(myArray, sizeM);
-
- for (int i = 1; i < N; i++)
- {
- double **output = createSquareArray(sizeM);
- output = multSquareArrays(originalCopy, intermediate, output, sizeM);
- //copy output into intermediate
- intermediate = copySquareDoubleArray(output, sizeM);
-
- freeSquareDoubleArray(output, sizeM);
- }
-
- freeSquareDoubleArray(intermediate, sizeM);
- freeSquareDoubleArray(originalCopy, sizeM);
-
- return 0;
- }
- //Creates a copy of a square double array. Must be freed outside.
- double** copySquareDoubleArray(double** myArray, int size)
- {
- double **myCopy = (double**)malloc( sizeof(double*) * size );
- for (int i = 0; i < size; i++)
- {
- myCopy[i] = (double*)malloc( sizeof(double) * size );
- for (int j = 0; j < size; j++)
- {
- myCopy[i][j] = myArray[i][j];
- }
-
- }
-
- return myCopy;
- }
- double **multSquareArrays(double **original, double **intermediate, double **output, int size)
- {
- for (int i = 0; i < size; i++)
- {
- for (int j = 0; j < size; j++)
- {
- for (int k = 0; k < size; k++)
- {
- //outArray[i,j] += A[i,k] * B[k,j]
- output[i][j] += original[i][k] * intermediate[k][j];
- }
- }
- }
-
- return output;
- }
- //Simple random double function that I found. rand/max gives a fraction
- //which is multiplied by the range.
- double doubleRand(double low, double high)
- {
- return ( (double)rand() * ( high - low ) ) / (double)RAND_MAX + low;
- }
- int checkInput(int argc, char **argv)
- {
- //~ if ( !isInputTwoNumbers(argc, argv) )
- if ( !isInputThreeNumbers(argc, argv) )
- {
- printf("Input must be three positive integers!\n");
- printTextFile(HELP_TEXT_PATH);
- exit( -1);
- }
- //I can add more checks for isDigit and such here.
-
- return 0;
- }
- _Bool isInputTwoNumbers(int argc, char **argv)
- {
- if (argc != 3)
- {
- return FALSE;
- }
- else
- {
- for (int i = 1; i < argc; i++) //Start at 1 to skip name.
- {
- //if any character not digit return false.
- if ( !isStringAllDigits(argv[i]) )
- {
- return FALSE;
- }
- }
- }
-
- return TRUE;
- }
- _Bool isInputThreeNumbers(int argc, char **argv)
- {
- if (argc != 4)
- {
- return FALSE;
- }
- else
- {
- for (int i = 1; i < argc; i++) //Start at 1 to skip name.
- {
- //if any character not digit return false.
- if ( !isStringAllDigits(argv[i]) )
- {
- return FALSE;
- }
- }
- }
-
- return TRUE;
- }
- //Returns TRUE if all characters are digits.
- _Bool isStringAllDigits(char* myString)
- {
- int c = 0;
- while (myString[c] != 0)
- {
- if ( !isdigit(myString[c]) )
- {
- return FALSE;
- }
-
- c++;
- }
-
- return TRUE;
- }
- //Timer function. Returns elapsed time.
- double getElapsedTime(struct timespec start, struct timespec finish)
- {
- double timeElapsed = 0;
- clock_gettime(CLOCK_MONOTONIC, &finish);//end
- timeElapsed = (finish.tv_sec - start.tv_sec);
- timeElapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0; //convert to nanoseconds
- return timeElapsed;
- }
- //Check if user needs help.
- int checkForHelpCommands(int argc, char** argv)
- {
- if ( ((argc > 1) && strIsHelp(argv[1])) || (argc == 1) )
- {
- printTextFile(HELP_TEXT_PATH);
-
- exit(0);
- }
-
- return 0;
- }
- //Returns true if input string is a help command.
- _Bool strIsHelp(char* aString)
- {
- if ( (strcmp(aString, "help") == 0)
- || (strcmp(aString, "-help") == 0)
- || (strcmp(aString, "--help") == 0)
- || (strcmp(aString, "h") == 0)
- || (strcmp(aString, "-h") == 0)
- || (strcmp(aString, "--h") == 0)
- )
- {
- return TRUE;
- }
-
- return FALSE;
- }
- //print a text file. Input string of the filename-path
- void printTextFile(char* inputPath)
- {
- FILE* myFile = fopen(inputPath, "r");
-
- int c; //int because EOF is usually negative.
- if ( myFile )
- {
- while ( (c = getc(myFile)) != EOF )
- {
- putchar(c);
- }
-
- fclose(myFile);
- }
- }
- void printSquareDoubleArray(double **myArray, int size)
- {
- for (int i = 0; i < size; i++)
- {
- for (int j = 0; j < size; j++)
- {
- printf("%f", myArray[i][j]);
- if ( j != size - 1 )
- {
- printf("\t");
- }
- }
- printf("\n");
- }
- printf("\n");
- }
- #endif
|