369 lines
7.2 KiB
C
369 lines
7.2 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <omp.h>
|
|
|
|
int *matA = 0;
|
|
int *matB = 0;
|
|
int *matResult = 0;
|
|
int matricesize;
|
|
double *matAdouble = 0;
|
|
double *matBdouble = 0;
|
|
double *matResultDouble = 0;
|
|
|
|
/*
|
|
* validate commandline arguments, set global variables as required or inform user of usage and quit the program
|
|
*/
|
|
void validateArguments(int argc, const char * argv[])
|
|
{
|
|
if (argc != 3)
|
|
{
|
|
printf("two parameters expected: filename mode\n");
|
|
exit(1);
|
|
}
|
|
|
|
if (strcmp(argv[2],"assembler") != 0 && strcmp(argv[2],"c_row") != 0 && strcmp(argv[2],"c_double") != 0 && strcmp(argv[2],"c_column") != 0) {
|
|
printf("Second parameter is invalid.\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Schöne, übersichtliche Matrixausgabe
|
|
*/
|
|
void printMatrixNice(){
|
|
int size = matricesize * matricesize;
|
|
int i;
|
|
int j = 0;
|
|
|
|
printf("Matrixgröße: %d\n", matricesize); //erste Zeile = Matrixgröße
|
|
|
|
for(i = 0; i < size; i++){
|
|
printf("%d\t", matResult[i]); //print Element
|
|
j++;
|
|
|
|
if(j % matricesize == 0) // j vielfaches von matricesize?
|
|
printf("\n"); // next line
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Schöne, übersichtliche Matrixausgabe von matResultDouble
|
|
*/
|
|
void printMatrixDoubleNice(){
|
|
int size = matricesize * matricesize;
|
|
int i;
|
|
int j = 0;
|
|
|
|
printf("Matrixgröße: %d\n", matricesize); //erste Zeile = Matrixgröße
|
|
|
|
for(i = 0; i < size; i++){
|
|
printf("%.5f\t", matResultDouble[i]); //print Element
|
|
j++;
|
|
|
|
if(j % matricesize == 0) // j vielfaches von matricesize?
|
|
printf("\n"); // next line
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Gibt Ergebnismatrix aus
|
|
*/
|
|
void printMatrix(){
|
|
int size = matricesize * matricesize; //size = größe des arrays
|
|
int i;
|
|
|
|
|
|
|
|
printf("%d\n", matricesize); // erste Zeile = Matrixgröße
|
|
|
|
for(i = 0; i < size; i++){ // Zeilenumsprung nach jedem Element
|
|
printf("%d\n", matResult[i]);
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* Gibt Ergebnismatrix von matResultDouble aus
|
|
*/
|
|
void printMatrixDouble(){
|
|
int size = matricesize * matricesize; //size = größe des arrays
|
|
int i;
|
|
|
|
|
|
printf("%d\n", matricesize); // erste Zeile = Matrixgröße
|
|
|
|
for(i = 0; i < size; i++){ // Zeilenumsprung nach jedem Element
|
|
printf("%0.5f\n", matResultDouble[i]);
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Berechnet Double-Matrizen-Multiplikation und adressiert hierbei spaltenweise
|
|
*
|
|
*/
|
|
void multiplyCDouble(){
|
|
|
|
//initialisiere lokale Variablen
|
|
int i, j;
|
|
int matResult_index;
|
|
|
|
|
|
#pragma omp parallel for
|
|
|
|
//Schleifen über Elemente der Ergebismatrix
|
|
for(i = 1; i <= matricesize; i++){
|
|
matResult_index = i - 1;
|
|
for(j = 1; j <= matricesize; j++){
|
|
|
|
double result = 0; //initialisiere lokale variablen
|
|
double mul;
|
|
int k, matA_index, matB_index;
|
|
|
|
|
|
for(k = 1; k <= matricesize; k++){ //Schleife über k (-> Summe)
|
|
matA_index = (j * matricesize) - matricesize + k; //Berechne Index von Matrix A
|
|
matB_index = (k * matricesize) - matricesize + i; //Berechne Index von Matrix B
|
|
|
|
mul = matAdouble[matA_index - 1] * matBdouble[matB_index - 1]; //Multipliziere passende Matrixeinträge
|
|
|
|
result += mul; // Summe!
|
|
}
|
|
|
|
|
|
matResultDouble[matResult_index] = result; //c(ij) an passendem Platz im Array abspeichern
|
|
matResult_index += matricesize; // matResult_index anpassen (spaltenweise Adressierung)
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* Spaltenweise Adressierung
|
|
*
|
|
* Schreibe Werte in matResult in folgender Reihenfolge:
|
|
*
|
|
* 1 4 7
|
|
* 2 5 8
|
|
* 3 6 9
|
|
*/
|
|
void multiplyCbyColumn(){
|
|
|
|
//initialisiere lokale variablen
|
|
int i, j;
|
|
int matResult_index;
|
|
|
|
|
|
#pragma omp parallel for
|
|
|
|
for(i = 1; i <= matricesize; i++){
|
|
matResult_index = i - 1; //Array-Index beginnt bei 0
|
|
|
|
for(j = 1; j <= matricesize; j++){
|
|
matResult[matResult_index] = get_cij(j, i); //Aufruf von get_cij
|
|
matResult_index += matricesize; //matResult_index + matricesizem, da spaltenweise Adressierung
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Zeilenweise Adressierung
|
|
*
|
|
* Schreibe Werte in matResult in folgender Reihenfolge:
|
|
*
|
|
* 1 2 3
|
|
* 4 5 6
|
|
* 7 8 9
|
|
*/
|
|
void multiplyCbyRow(){
|
|
|
|
int i, j;
|
|
int matResult_index = 0; //Array-Index beginnt bei 0
|
|
|
|
|
|
#pragma omp parallel for
|
|
//Schleifen über Elemente der Ergebnismatrix
|
|
for(i = 1; i <= matricesize; i++){
|
|
for(j = 1; j <= matricesize; j++){
|
|
matResult[matResult_index] = get_cij(i, j); //Aufruf von get_cij
|
|
matResult_index++; //Array-Index um 1 erhöreh -> zeilenweise Adressierung
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* return int
|
|
* konsumiert Indizes i und j und gibt Summe von k=1 bis m=matricesize von (a(ik) * b(kj)) zurück
|
|
*/
|
|
int get_cij(int i, int j){
|
|
|
|
int result = 0, k, matA_index, matB_index, mul; //initialisiere lokale variablen
|
|
|
|
|
|
for(k = 1; k <= matricesize; k++){ //Schleife über k (-> Summe)
|
|
matA_index = (i * matricesize) - matricesize + k; //Berechne Index von Matrix A
|
|
matB_index = (k * matricesize) - matricesize + j; //Berechne Index von Matrix B
|
|
|
|
mul = matA[matA_index - 1] * matB[matB_index - 1]; //Multipliziere passende Matrixeinträge
|
|
|
|
result += mul; // Summe!
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* read a matrice file into memory
|
|
*/
|
|
void readMatricefile(const char *file, char bDouble)
|
|
{
|
|
// open file
|
|
FILE * pFile;
|
|
char line[16];
|
|
pFile = fopen(file, "r");
|
|
|
|
if (pFile == NULL)
|
|
{
|
|
printf("Accessing input file failed\n");
|
|
exit(1);
|
|
}
|
|
|
|
// Determine matrice size
|
|
fgets(line, 16, pFile);
|
|
matricesize = atoi(line);
|
|
|
|
// Allocate memory
|
|
int size = matricesize*matricesize;
|
|
|
|
if (bDouble)
|
|
{
|
|
// Double required
|
|
matAdouble = (double*) malloc(size * sizeof(double));
|
|
matBdouble = (double*) malloc(size * sizeof(double));
|
|
matResultDouble = (double*) malloc(size * sizeof(double));
|
|
|
|
if (matAdouble == NULL || matBdouble == NULL || matResultDouble == NULL)
|
|
{
|
|
printf("Error allocating memory.\n");
|
|
exit(1);
|
|
}
|
|
|
|
// continue reading
|
|
int i = 0;
|
|
while (fgets(line, 16, pFile) != NULL && i < 2*size)
|
|
{
|
|
if (i < size)
|
|
matAdouble[i] = strtod(line, NULL);
|
|
else
|
|
matBdouble[i - size] = strtod(line, NULL);
|
|
|
|
i++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Integers required
|
|
matA = (int*) malloc(size * sizeof(int));
|
|
matB = (int*) malloc(size * sizeof(int));
|
|
matResult = (int*) malloc(size * sizeof(int));
|
|
|
|
if (matA == NULL || matB == NULL || matResult == NULL)
|
|
{
|
|
printf("Error allocating memory.\n");
|
|
exit(1);
|
|
}
|
|
|
|
// continue reading
|
|
int i = 0;
|
|
while (fgets(line, 16, pFile) != NULL && i < 2*size)
|
|
{
|
|
if (i < size)
|
|
matA[i] = atoi(line);
|
|
else
|
|
matB[i - size] = atoi(line);
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
// done
|
|
fclose(pFile);
|
|
}
|
|
|
|
int main (int argc, const char * argv[])
|
|
{
|
|
// check we got valid arguments, else quit
|
|
validateArguments(argc, argv);
|
|
|
|
// read input matrice file
|
|
readMatricefile(argv[1], (strcmp(argv[2],"c_double") == 0) );
|
|
|
|
|
|
// ---- insert your code here ----
|
|
|
|
if(!strcmp(argv[2],"c_row")){ //parameter c_row
|
|
multiplyCbyRow();
|
|
printMatrixNice();
|
|
//printMatrix();
|
|
}
|
|
else if(!strcmp(argv[2],"c_column")){ //parameter c_column
|
|
multiplyCbyColumn();
|
|
printMatrixNice();
|
|
//printMatrix();
|
|
}
|
|
else if(!strcmp(argv[2],"c_double")){ //parameter c_double
|
|
multiplyCDouble();
|
|
printMatrixDoubleNice();
|
|
//printMatrixDouble();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// clear memory
|
|
if ((strcmp(argv[2],"c_double") != 0))
|
|
{
|
|
free(matA);
|
|
free(matB);
|
|
free(matResult);
|
|
}
|
|
else
|
|
{
|
|
free(matAdouble);
|
|
free(matBdouble);
|
|
free(matResultDouble);
|
|
}
|
|
|
|
return 0;
|
|
} |