Browse Source

Init sparse matrices

master
Apostolos Fanakis 6 years ago
parent
commit
c4eb6d0c17
No known key found for this signature in database GPG Key ID: 56CE2DEDE9F1FB78
  1. 4
      serial/Makefile
  2. 9
      serial/serial_gs_pagerank.c
  3. 194
      serial/serial_gs_pagerank_functions.c
  4. 28
      serial/serial_gs_pagerank_functions.h
  5. 126
      serial/sparse_matrix.c
  6. 29
      serial/sparse_matrix.h

4
serial/Makefile

@ -7,8 +7,8 @@ CC = gcc
RM = rm -f RM = rm -f
CFLAGS_DEBUG=-O0 -g -I. CFLAGS_DEBUG=-O0 -g -I.
CFLAGS=-O3 -I. CFLAGS=-O3 -I.
OBJ=serial_gs_pagerank.o serial_gs_pagerank_functions.o OBJ=serial_gs_pagerank.o serial_gs_pagerank_functions.o sparse_matrix.o
DEPS=serial_gs_pagerank_functions.h DEPS=serial_gs_pagerank_functions.h sparse_matrix.h
# ========================================== # ==========================================
# TARGETS # TARGETS

9
serial/serial_gs_pagerank.c

@ -1,18 +1,21 @@
#include <sys/time.h> #include <sys/time.h>
#include "serial_gs_pagerank_functions.h" #include "serial_gs_pagerank_functions.h"
#include "sparse_matrix.h"
struct timeval startwtime, endwtime; struct timeval startwtime, endwtime;
double seq_time; double seq_time;
int main(int argc, char **argv) { int main(int argc, char **argv) {
int **directedWebGraph; SparseMatrix transitionMatrix;
double **transitionMatrix, *pagerankVector; double *pagerankVector;
Parameters parameters; Parameters parameters;
transitionMatrix = createSparseMatrix();
parseArguments(argc, argv, &parameters); parseArguments(argc, argv, &parameters);
initialize(&directedWebGraph, &transitionMatrix, &pagerankVector, &parameters); initialize(&transitionMatrix, &pagerankVector, &parameters);
// Starts wall-clock timer // Starts wall-clock timer
gettimeofday (&startwtime, NULL); gettimeofday (&startwtime, NULL);

194
serial/serial_gs_pagerank_functions.c

@ -9,10 +9,11 @@ const char *ARGUMENT_OUTPUT_FILENAME = "-o";
const int NUMERICAL_BASE = 10; const int NUMERICAL_BASE = 10;
char *DEFAULT_OUTPUT_FILENAME = "pagerank_output"; char *DEFAULT_OUTPUT_FILENAME = "pagerank_output";
const int MAX_PAGE_LINKS_TEXT_SIZE = 4096;
// ==================== PAGERANK ==================== // ==================== PAGERANK ====================
int pagerank(double ***transitionMatrix, double **pagerankVector, Parameters parameters) { int pagerank(SparseMatrix *transitionMatrix, double **pagerankVector, Parameters parameters) {
int iterations = 0; int iterations = 0;
double delta, double delta,
*vectorDifference = (double *) malloc(parameters.numberOfPages * sizeof(double)), *vectorDifference = (double *) malloc(parameters.numberOfPages * sizeof(double)),
@ -40,10 +41,13 @@ int pagerank(double ***transitionMatrix, double **pagerankVector, Parameters par
do { do {
memcpy(previousPagerankVector, *pagerankVector, parameters.numberOfPages * sizeof(double)); memcpy(previousPagerankVector, *pagerankVector, parameters.numberOfPages * sizeof(double));
matrixVectorMultiplication(*transitionMatrix, previousPagerankVector, matrixVectorMultiplication(transitionMatrix, previousPagerankVector,
linksFromConvergedPagesPagerankVector, convergedPagerankVector,
pagerankVector, parameters.numberOfPages, parameters.dampingFactor); pagerankVector, parameters.numberOfPages, parameters.dampingFactor);
for (int i=0; i<parameters.numberOfPages; ++i) {
(*pagerankVector)[i] += linksFromConvergedPagesPagerankVector[i] + convergedPagerankVector[i];
}
if (parameters.history) { if (parameters.history) {
savePagerankToFile(parameters.outputFilename, iterations != 0, savePagerankToFile(parameters.outputFilename, iterations != 0,
*pagerankVector, parameters.numberOfPages); *pagerankVector, parameters.numberOfPages);
@ -54,7 +58,7 @@ int pagerank(double ***transitionMatrix, double **pagerankVector, Parameters par
} }
delta = vectorNorm(vectorDifference, parameters.numberOfPages); delta = vectorNorm(vectorDifference, parameters.numberOfPages);
if (!iterations % 10) { if (iterations && !iterations % 10) {
for (int i=0; i<parameters.numberOfPages; ++i) { for (int i=0; i<parameters.numberOfPages; ++i) {
double temp = fabs((*pagerankVector)[i] - previousPagerankVector[i]) / fabs(previousPagerankVector[i]); double temp = fabs((*pagerankVector)[i] - previousPagerankVector[i]) / fabs(previousPagerankVector[i]);
if (temp < parameters.convergenceCriterion){ if (temp < parameters.convergenceCriterion){
@ -67,12 +71,11 @@ int pagerank(double ***transitionMatrix, double **pagerankVector, Parameters par
if (converganceMatrix[i] == true) { if (converganceMatrix[i] == true) {
for (int j=0; j<parameters.numberOfPages; ++j){ for (int j=0; j<parameters.numberOfPages; ++j){
if (converganceMatrix[j] == false){ if (converganceMatrix[j] == false){
linksFromConvergedPages[i][j] = (*transitionMatrix)[i][j]; SparseMatrixElement *element = getElement(*transitionMatrix, i, j);
linksFromConvergedPages[i][j] = element != NULL ? element->value : 0;
} }
// Zeros out CN and CC sub-matrices deleteElement(transitionMatrix, i, j);
(*transitionMatrix)[i][j] = 0; deleteElement(transitionMatrix, j, i);
// Zeros out NC sub-matrix
(*transitionMatrix)[j][i] = 0;
} }
double sum = 0; double sum = 0;
@ -104,14 +107,14 @@ int pagerank(double ***transitionMatrix, double **pagerankVector, Parameters par
* from the file and creates the initial transition probability distribution * from the file and creates the initial transition probability distribution
* matrix. * matrix.
*/ */
void initialize(int ***directedWebGraph, double ***transitionMatrix, void initialize(SparseMatrix *transitionMatrix,
double **pagerankVector, Parameters *parameters) { double **pagerankVector, Parameters *parameters) {
// Reads web graph from file // Reads web graph from file
if ((*parameters).verbose) { if ((*parameters).verbose) {
printf("----- Reading graph from file -----\n"); printf("----- Reading graph from file -----\n");
} }
readGraphFromFile(directedWebGraph, parameters); generateNormalizedTransitionMatrixFromFile(transitionMatrix, parameters);
// Outputs the algorithm parameters to the console // Outputs the algorithm parameters to the console
if ((*parameters).verbose) { if ((*parameters).verbose) {
@ -135,49 +138,8 @@ void initialize(int ***directedWebGraph, double ***transitionMatrix,
(*pagerankVector)[i] = webUniformProbability; (*pagerankVector)[i] = webUniformProbability;
} }
// Generates the initial transition matrix (matrix P).
generateNormalizedTransitionMatrix(transitionMatrix, *directedWebGraph, *parameters);
// Transposes the transition matrix (P^T). // Transposes the transition matrix (P^T).
transposeMatrix(transitionMatrix, (*parameters).numberOfPages, (*parameters).numberOfPages); transposeSparseMatrix(transitionMatrix);
}
/*
* generateNormalizedTransitionMatrix generates the normalized transition matrix
* from the graph data (matrix P').
*/
void generateNormalizedTransitionMatrix(double ***transitionMatrix,
int **directedWebGraph, Parameters parameters) {
// Allocates memory for the transitionMatrix rows
(*transitionMatrix) = (double **) malloc(parameters.numberOfPages * sizeof(double *));
for (int i=0; i<parameters.numberOfPages; ++i) {
// Allocates memory for this row's columns
(*transitionMatrix)[i] = (double *) malloc(parameters.numberOfPages * sizeof(double));
// Calculates the outdegree of this page
int pageOutdegree = 0;
for (int j=0; j<parameters.numberOfPages; ++j) {
pageOutdegree += directedWebGraph[i][j];
}
// Populates this row of the transition matrix
if (pageOutdegree != 0) {
// Calculates the uniform probability once.
double pageUniformProbability = 1. / pageOutdegree;
for (int j=0; j<parameters.numberOfPages; ++j) {
if (directedWebGraph[i][j] == 1){
(*transitionMatrix)[i][j] = pageUniformProbability;
} else {
(*transitionMatrix)[i][j] = 0;
}
}
} else {
for (int j=0; j<parameters.numberOfPages; ++j) {
(*transitionMatrix)[i][j] = 0;
}
}
}
} }
// ==================== MATH UTILS ==================== // ==================== MATH UTILS ====================
@ -186,26 +148,22 @@ void generateNormalizedTransitionMatrix(double ***transitionMatrix,
* matrixVectorMultiplication calculates the product of the multiplication * matrixVectorMultiplication calculates the product of the multiplication
* between a matrix and the a vector in a cheap way. * between a matrix and the a vector in a cheap way.
*/ */
void matrixVectorMultiplication(double **transitionMatrix, double *previousPagerankVector, void matrixVectorMultiplication(SparseMatrix *transitionMatrix, double *previousPagerankVector,
double *linksFromConvergedPagesPagerankVector, double *convergedPagerankVector,
double **pagerankVector, int vectorSize, double dampingFactor) { double **pagerankVector, int vectorSize, double dampingFactor) {
double webUniformProbability = 1. / vectorSize; double webUniformProbability = 1. / vectorSize;
for (int i=0; i<vectorSize; ++i) { sparseMatrixVectorMultiplication(*transitionMatrix, previousPagerankVector,
double sum = 0; pagerankVector, vectorSize);
for (int j=0; j<vectorSize; ++j) { for (int i=0; i<vectorSize; ++i) {
sum += transitionMatrix[i][j] * previousPagerankVector[j]; (*pagerankVector)[i] = dampingFactor * (*pagerankVector)[i];
}
(*pagerankVector)[i] = dampingFactor * sum;
} }
double normDifference = vectorNorm(previousPagerankVector, vectorSize) - double normDifference = vectorNorm(previousPagerankVector, vectorSize) -
vectorNorm(*pagerankVector, vectorSize); vectorNorm(*pagerankVector, vectorSize);
for (int i=0; i<vectorSize; ++i) { for (int i=0; i<vectorSize; ++i) {
(*pagerankVector)[i] += normDifference * webUniformProbability + (*pagerankVector)[i] += normDifference * webUniformProbability;
linksFromConvergedPagesPagerankVector[i] + convergedPagerankVector[i];
} }
} }
@ -222,32 +180,6 @@ double vectorNorm(double *vector, int vectorSize) {
return norm; return norm;
} }
/*
* transposeMatrix transposes the matrix passed (by reference) in the arguments.
*/
void transposeMatrix(double ***matrix, int rows, int columns) {
// Transposes the matrix
// Rows become columns and vice versa
double **tempArray = (double **) malloc(columns * sizeof(double *));
for (int i=0; i<columns; ++i) {
tempArray[i] = malloc(rows * sizeof(double));
for (int j=0; j<rows; ++j) {
tempArray[i][j] = (*matrix)[j][i];
}
}
// TODO free memory
//double **pointerToFreeMemoryLater = *matrix;
*matrix = tempArray;
/*for (int i=0; i<rows; ++i) {
free(pointerToFreeMemoryLater[i]);
}
free(pointerToFreeMemoryLater);*/
}
// ==================== PROGRAM INPUT AND OUTPUT UTILS ==================== // ==================== PROGRAM INPUT AND OUTPUT UTILS ====================
/* /*
@ -323,7 +255,8 @@ void parseArguments(int argumentCount, char **argumentVector, Parameters *parame
* readGraphFromFile loads the file supplied in the command line arguments to an * readGraphFromFile loads the file supplied in the command line arguments to an
* array (directedWebGraph) that represents the graph. * array (directedWebGraph) that represents the graph.
*/ */
void readGraphFromFile(int ***directedWebGraph, Parameters *parameters) { void generateNormalizedTransitionMatrixFromFile(SparseMatrix *transitionMatrix,
Parameters *parameters){
FILE *graphFile; FILE *graphFile;
// Opens the file for reading // Opens the file for reading
@ -333,38 +266,71 @@ void readGraphFromFile(int ***directedWebGraph, Parameters *parameters) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Reads the dimensions of the (square) array from the file int pageIndex, count = 0;
int readChar, numberOfLines=0; while (fscanf(graphFile, "%d:", &pageIndex) != EOF) {
while((readChar = fgetc(graphFile))) { if (!(pageIndex%51050)) {
// Breaks if end of file printf("\t%d\t%d%%\n", pageIndex, ++count);
if (readChar == EOF) break;
// Otherwise, if the character is a break line, adds one to the count of lines
if (readChar == '\n') {
++numberOfLines;
} }
}
if ((*parameters).verbose) { char *restOfLine = malloc(MAX_PAGE_LINKS_TEXT_SIZE);
printf("Line count of file is %d \n", numberOfLines + 1); if (!fgets(restOfLine, MAX_PAGE_LINKS_TEXT_SIZE, graphFile)) {
} exit(EXIT_FAILURE);
}
// Each line of the file represents one page of the graph char *token = strtok(restOfLine, " ");
(*parameters).numberOfPages = numberOfLines + 1;
rewind(graphFile);
// Allocates memory and loads values into directedWebGraph (matrix A) while (token != NULL) {
// Allocates memory for the rows if (strcmp(token, "\n") == 0) {
(*directedWebGraph) = (int **) malloc((*parameters).numberOfPages * sizeof(int *)); //token = strtok (NULL, " ");
break;
}
for (int i=0; i<(*parameters).numberOfPages; ++i) { int outLink = atoi(token);
// Allocates memory for the columns of this row if (outLink != -1) {
(*directedWebGraph)[i] = (int *) malloc((*parameters).numberOfPages * sizeof(int)); apendElement(transitionMatrix, 1, pageIndex, outLink);
// Reads values from the file }
for (int j=0; j<(*parameters).numberOfPages; ++j) { token = strtok (NULL, " ");
if (!fscanf(graphFile, "%d ", &(*directedWebGraph)[i][j])) { }
}
printf("\t100%%\n");
printf("number of edges = %d\n", transitionMatrix->elements);
(*parameters).numberOfPages = pageIndex + 1;
int currentRow = transitionMatrix->firstElement->rowIndex;
SparseMatrixElement *startElement = transitionMatrix->firstElement;
while(true) {
int pageOutdegree = 1;
SparseMatrixElement *currentElement = startElement->nextElement;
// Calculates current page's outdegree
while (currentElement != NULL) {
if (currentElement->rowIndex == currentRow) {
++pageOutdegree;
currentElement = currentElement->nextElement;
} else {
break; break;
} }
} }
// Assigns the value 1/outdegree to current page's columns
currentElement = startElement;
for (int i=0; i<pageOutdegree; ++i) {
if (currentElement->rowIndex == currentRow) {
currentElement->value = 1. / pageOutdegree;
currentElement = currentElement->nextElement;
} else {
break;
}
}
// Reached the last element;
if (currentElement == NULL) {
break;
}
startElement = currentElement;
currentRow = startElement->rowIndex;
} }
fclose(graphFile); fclose(graphFile);

28
serial/serial_gs_pagerank_functions.h

@ -7,6 +7,8 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "sparse_matrix.h"
/* /*
* Constant strings that store the command line options available. * Constant strings that store the command line options available.
*/ */
@ -23,6 +25,8 @@ extern const int NUMERICAL_BASE;
// Default filename used for the output. // Default filename used for the output.
extern char *DEFAULT_OUTPUT_FILENAME; extern char *DEFAULT_OUTPUT_FILENAME;
extern const int MAX_PAGE_LINKS_TEXT_SIZE;
// Declares a data structure to conveniently hold the algorithm's parameters. // Declares a data structure to conveniently hold the algorithm's parameters.
typedef struct parameters { typedef struct parameters {
int numberOfPages, maxIterations; int numberOfPages, maxIterations;
@ -31,6 +35,9 @@ typedef struct parameters {
char *outputFilename, *graphFilename; char *outputFilename, *graphFilename;
} Parameters; } Parameters;
//extern typedef SparseMatrixElement;
//extern typedef SparseMatrix;
// Function validUsage outputs the correct way to use the program with command // Function validUsage outputs the correct way to use the program with command
// line arguments. // line arguments.
void validUsage(char *programName); void validUsage(char *programName);
@ -45,26 +52,17 @@ void parseArguments(int argumentCount, char **argumentVector, Parameters *parame
// Function readGraphFromFile loads adjacency matrix, that represents the web // Function readGraphFromFile loads adjacency matrix, that represents the web
// graph, stored in the file provided in the command line arguments to the array // graph, stored in the file provided in the command line arguments to the array
// directedWebGraph. // directedWebGraph.
void readGraphFromFile(int ***directedWebGraph, Parameters *parameters); void generateNormalizedTransitionMatrixFromFile(SparseMatrix *transitionMatrix, Parameters *parameters);
// Function savePagerankToFile appends or overwrites the pagerank vector // Function savePagerankToFile appends or overwrites the pagerank vector
// "pagerankVector" to the file with the filename supplied in the arguments // "pagerankVector" to the file with the filename supplied in the arguments
void savePagerankToFile(char *filename, bool append, double *pagerankVector, void savePagerankToFile(char *filename, bool append, double *pagerankVector,
int vectorSize); int vectorSize);
// Function generateNormalizedTransitionMatrix generates the normalized
// transition matrix from the web graph data.
void generateNormalizedTransitionMatrix(double ***transitionMatrix,
int **directedWebGraph, Parameters parameters);
// Function transposeMatrix transposes a matrix.
void transposeMatrix(double ***matrix, int rows, int columns);
// Function initialize allocates required memory for arrays, reads the dataset // Function initialize allocates required memory for arrays, reads the dataset
// from the file and creates the transition probability distribution matrix. // from the file and creates the transition probability distribution matrix.
void initialize( void initialize(
int ***directedWebGraph, /*This is matrix G (web graph)*/ SparseMatrix *transitionMatrix, /*This is matrix A (transition probability distribution matrix)*/
double ***transitionMatrix, /*This is matrix A (transition probability distribution matrix)*/
double **pagerankVector, /*This is the resulting pagerank vector*/ double **pagerankVector, /*This is the resulting pagerank vector*/
Parameters *parameters Parameters *parameters
); );
@ -74,13 +72,13 @@ double vectorNorm(double *vector, int vectorSize);
// Function matrixVectorMultiplication calculates the product of the // Function matrixVectorMultiplication calculates the product of the
// multiplication between a matrix and the a vector. // multiplication between a matrix and the a vector.
void matrixVectorMultiplication(double **transitionMatrix, double *previousPagerankVector, void matrixVectorMultiplication(SparseMatrix *transitionMatrix,
double *linksFromConvergedPagesPagerankVector, double *convergedPagerankVector, double *previousPagerankVector, double **pagerankVector, int vectorSize,
double **pagerankVector, int vectorSize, double dampingFactor); double dampingFactor);
// Function pagerank iteratively calculates the pagerank of each page until // Function pagerank iteratively calculates the pagerank of each page until
// either the convergence criterion is met or the maximum number of iterations // either the convergence criterion is met or the maximum number of iterations
// is reached. // is reached.
int pagerank(double ***transitionMatrix, double **pagerankVector, Parameters parameters); int pagerank(SparseMatrix *transitionMatrix, double **pagerankVector, Parameters parameters);
#endif // SERIAL_GS_PAGERANK_FUNCTIONS_H #endif // SERIAL_GS_PAGERANK_FUNCTIONS_H

126
serial/sparse_matrix.c

@ -0,0 +1,126 @@
#include "sparse_matrix.h"
SparseMatrix createSparseMatrix() {
SparseMatrix sparseMatrix;
sparseMatrix.elements = 0;
sparseMatrix.firstElement = NULL;
return sparseMatrix;
}
void apendElement(SparseMatrix *sparseMatrix, double value, int row, int column) {
// Creates the new element
SparseMatrixElement *newElement = (SparseMatrixElement *) malloc(sizeof(SparseMatrixElement));
newElement->value = value;
newElement->rowIndex = row;
newElement->columnIndex = column;
newElement->nextElement = NULL;
if (sparseMatrix->firstElement == NULL) {
// Sparse matrix is empty, this is the first element
sparseMatrix->firstElement = newElement;
} else {
//Gets last element of the matrix
SparseMatrixElement *lastElement = sparseMatrix->firstElement;
while (lastElement->nextElement != NULL) {
lastElement = lastElement->nextElement;
}
lastElement->nextElement = newElement;
}
sparseMatrix->elements = sparseMatrix->elements + 1;
}
bool deleteElement(SparseMatrix *sparseMatrix, int row, int column) {
if (sparseMatrix->elements == 0) {
// Matrix is empty, nothing can be deleted
return false;
} else if (sparseMatrix->elements == 1) {
// Matrix has one element. Deletes it.
free(sparseMatrix->firstElement);
sparseMatrix->firstElement = NULL;
sparseMatrix->elements = sparseMatrix->elements - 1;
return true;
}
SparseMatrixElement *currentElement = sparseMatrix->firstElement;
if (currentElement->rowIndex == row && currentElement->columnIndex == column) {
sparseMatrix->firstElement = currentElement->nextElement;
free(currentElement);
sparseMatrix->elements = sparseMatrix->elements - 1;
return true;
}
// Matrix has multiple elements. Finds the first element that has the coordinates
// (row,column) and deletes it.
for (int i=0; i<sparseMatrix->elements - 1; ++i) {
SparseMatrixElement *nextElement = currentElement->nextElement;
if (nextElement->rowIndex == row && nextElement->columnIndex == column) {
currentElement->nextElement = nextElement->nextElement;
free(nextElement);
sparseMatrix->elements = sparseMatrix->elements - 1;
return true;
} else {
currentElement = currentElement->nextElement;
}
}
}
SparseMatrixElement *getElement(SparseMatrix sparseMatrix, int row, int column) {
SparseMatrixElement *currentElement = sparseMatrix.firstElement;
do {
if (currentElement->rowIndex == row && currentElement->columnIndex == column) {
return currentElement;
}
currentElement = currentElement->nextElement;
} while (currentElement != NULL);
return NULL;
}
void transposeSparseMatrix(SparseMatrix *sparseMatrix) {
SparseMatrixElement *currentElement = sparseMatrix->firstElement;
for (int i=0; i<sparseMatrix->elements; ++i) {
int temp = currentElement->rowIndex;
currentElement->rowIndex = currentElement->columnIndex;
currentElement->columnIndex = temp;
currentElement = currentElement->nextElement;
}
}
void sparseMatrixVectorMultiplication(SparseMatrix sparseMatrix,
double *vector, double **product, int vectorSize) {
// Initializes the elements of the product vector to zero
for (int i=0; i<vectorSize; ++i) {
(*product)[i] = 0;
}
SparseMatrixElement *element = sparseMatrix.firstElement;
for (int i=0; i<sparseMatrix.elements; ++i) {
int row = element->rowIndex, column = element->columnIndex;
if (row >= vectorSize) {
printf("Error at sparseMatrixVectorMultiplication. Matrix has more rows than vector!\n");
printf("row = %d\n", row);
exit(EXIT_FAILURE);
}
(*product)[row] = (*product)[row] + element->value * vector[column];
element = element->nextElement;
}
}
void printSparseMatrix(SparseMatrix sparseMatrix) {
if (sparseMatrix.elements == 0) {
return;
}
SparseMatrixElement *currentElement = sparseMatrix.firstElement;
for (int i=0; i<sparseMatrix.elements; ++i) {
printf("[%d,%d] = %f\n", currentElement->rowIndex,
currentElement->columnIndex, currentElement->value);
currentElement = currentElement->nextElement;
}
}

29
serial/sparse_matrix.h

@ -0,0 +1,29 @@
#ifndef SPARSE_MATRIX_H /* Include guard */
#define SPARSE_MATRIX_H
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct sparseMatrixElement {
double value;
int rowIndex, columnIndex;
struct sparseMatrixElement *nextElement;
} SparseMatrixElement;
typedef struct sparseMatrix {
int elements;
SparseMatrixElement *firstElement;
} SparseMatrix;
SparseMatrix createSparseMatrix();
void apendElement(SparseMatrix *sparseMatrix, double value, int row, int column);
bool deleteElement(SparseMatrix *sparseMatrix, int row, int column);
SparseMatrixElement *getElement(SparseMatrix sparseMatrix, int row, int column);
void transposeSparseMatrix(SparseMatrix *sparseMatrix);
void sparseMatrixVectorMultiplication(SparseMatrix sparseMatrix, double *vector,
double **product, int vectorSize);
void printSparseMatrix(SparseMatrix sparseMatrix);
#endif // SPARSE_MATRIX_H
Loading…
Cancel
Save