college/ws2010/gdi3/p3/prak3.c
2011-10-18 10:28:57 +02:00

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;
}