Reformat. Change indent to 2 spaces and line length to 80.

This commit is contained in:
Jan Eitzinger 2025-01-19 07:07:18 +01:00
parent 82824ec020
commit 6f1932cf4f
15 changed files with 1314 additions and 1259 deletions

View File

@ -1,5 +1,5 @@
--- ---
Language: Cpp Language: Cpp
# BasedOnStyle: WebKit # BasedOnStyle: WebKit
AccessModifierOffset: -4 AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign AlignAfterOpenBracket: DontAlign
@ -29,21 +29,21 @@ AttributeMacros:
BinPackArguments: false BinPackArguments: false
BinPackParameters: false BinPackParameters: false
BraceWrapping: BraceWrapping:
AfterCaseLabel: false AfterCaseLabel: false
AfterClass: false AfterClass: false
AfterControlStatement: Never AfterControlStatement: Never
AfterEnum: false AfterEnum: false
AfterFunction: true AfterFunction: true
AfterNamespace: false AfterNamespace: false
AfterObjCDeclaration: false AfterObjCDeclaration: false
AfterStruct: false AfterStruct: false
AfterUnion: false AfterUnion: false
AfterExternBlock: false AfterExternBlock: false
BeforeCatch: false BeforeCatch: false
BeforeElse: false BeforeElse: false
BeforeLambdaBody: false BeforeLambdaBody: false
BeforeWhile: false BeforeWhile: false
IndentBraces: false IndentBraces: false
SplitEmptyFunction: true SplitEmptyFunction: true
SplitEmptyRecord: true SplitEmptyRecord: true
SplitEmptyNamespace: true SplitEmptyNamespace: true
@ -56,19 +56,18 @@ BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true BreakStringLiterals: true
ColumnLimit: 90 ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:' CommentPragmas: "^ IWYU pragma:"
CompactNamespaces: false CompactNamespaces: false
ConstructorInitializerIndentWidth: 4 ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4
Cpp11BracedListStyle: false Cpp11BracedListStyle: false
DeriveLineEnding: true DeriveLineEnding: true
DerivePointerAlignment: false DerivePointerAlignment: false
DisableFormat: false DisableFormat: false
EmptyLineAfterAccessModifier: Never EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
BasedOnStyle: ''
ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerAllOnOneLineOrOnePerLine: false
AllowAllConstructorInitializersOnNextLine: true AllowAllConstructorInitializersOnNextLine: true
FixNamespaceComments: false FixNamespaceComments: false
@ -78,37 +77,37 @@ ForEachMacros:
- BOOST_FOREACH - BOOST_FOREACH
IfMacros: IfMacros:
- KJ_IF_MAYBE - KJ_IF_MAYBE
IncludeBlocks: Preserve IncludeBlocks: Preserve
IncludeCategories: IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2 Priority: 2
SortPriority: 0 SortPriority: 0
CaseSensitive: false CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)' - Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3 Priority: 3
SortPriority: 0 SortPriority: 0
CaseSensitive: false CaseSensitive: false
- Regex: '.*' - Regex: ".*"
Priority: 1 Priority: 1
SortPriority: 0 SortPriority: 0
CaseSensitive: false CaseSensitive: false
IncludeIsMainRegex: '(Test)?$' IncludeIsMainRegex: "(Test)?$"
IncludeIsMainSourceRegex: '' IncludeIsMainSourceRegex: ""
IndentAccessModifiers: false IndentAccessModifiers: false
IndentCaseLabels: false IndentCaseLabels: false
IndentCaseBlocks: false IndentCaseBlocks: false
IndentGotoLabels: true IndentGotoLabels: true
IndentPPDirectives: None IndentPPDirectives: None
IndentExternBlock: AfterExternBlock IndentExternBlock: AfterExternBlock
IndentWidth: 4 IndentWidth: 2
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
InsertTrailingCommas: None InsertTrailingCommas: None
JavaScriptQuotes: Leave JavaScriptQuotes: Leave
JavaScriptWrapImports: true JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature LambdaBodyIndentation: Signature
MacroBlockBegin: '' MacroBlockBegin: ""
MacroBlockEnd: '' MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
NamespaceIndentation: Inner NamespaceIndentation: Inner
ObjCBinPackProtocolList: Auto ObjCBinPackProtocolList: Auto
@ -126,11 +125,11 @@ PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60 PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0 PenaltyIndentedWhitespace: 0
PointerAlignment: Left PointerAlignment: Left
PPIndentWidth: -1 PPIndentWidth: -1
ReferenceAlignment: Pointer ReferenceAlignment: Pointer
ReflowComments: true ReflowComments: true
ShortNamespaceLines: 1 ShortNamespaceLines: 1
SortIncludes: CaseSensitive SortIncludes: CaseSensitive
SortJavaStaticImport: Before SortJavaStaticImport: Before
SortUsingDeclarations: true SortUsingDeclarations: true
SpaceAfterCStyleCast: false SpaceAfterCStyleCast: false
@ -147,30 +146,29 @@ SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1 SpacesBeforeTrailingComments: 1
SpacesInAngles: Never SpacesInAngles: Never
SpacesInConditionalStatement: false SpacesInConditionalStatement: false
SpacesInContainerLiterals: true SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix: SpacesInLineCommentPrefix:
Minimum: 1 Minimum: 1
Maximum: -1 Maximum: -1
SpacesInParentheses: false SpacesInParentheses: false
SpacesInSquareBrackets: false SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both BitFieldColonSpacing: Both
Standard: Latest Standard: Latest
StatementAttributeLikeMacros: StatementAttributeLikeMacros:
- Q_EMIT - Q_EMIT
StatementMacros: StatementMacros:
- Q_UNUSED - Q_UNUSED
- QT_REQUIRE_VERSION - QT_REQUIRE_VERSION
TabWidth: 8 TabWidth: 8
UseCRLF: false UseCRLF: false
UseTab: Never UseTab: Never
WhitespaceSensitiveMacros: WhitespaceSensitiveMacros:
- STRINGIZE - STRINGIZE
- PP_STRINGIZE - PP_STRINGIZE
- BOOST_PP_STRINGIZE - BOOST_PP_STRINGIZE
- NS_SWIFT_NAME - NS_SWIFT_NAME
- CF_SWIFT_NAME - CF_SWIFT_NAME
...

View File

@ -11,26 +11,26 @@
void* allocate(size_t alignment, size_t bytesize) void* allocate(size_t alignment, size_t bytesize)
{ {
int errorCode; int errorCode;
void* ptr; void* ptr;
errorCode = posix_memalign(&ptr, alignment, bytesize); errorCode = posix_memalign(&ptr, alignment, bytesize);
if (errorCode) { if (errorCode) {
if (errorCode == EINVAL) { if (errorCode == EINVAL) {
fprintf(stderr, "Error: Alignment parameter is not a power of two\n"); fprintf(stderr, "Error: Alignment parameter is not a power of two\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
}
if (errorCode == ENOMEM) {
fprintf(stderr, "Error: Insufficient memory to fulfill the request\n");
exit(EXIT_FAILURE);
}
} }
if (errorCode == ENOMEM) {
if (ptr == NULL) { fprintf(stderr, "Error: Insufficient memory to fulfill the request\n");
fprintf(stderr, "Error: posix_memalign failed!\n"); exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
} }
}
return ptr; if (ptr == NULL) {
fprintf(stderr, "Error: posix_memalign failed!\n");
exit(EXIT_FAILURE);
}
return ptr;
} }

1037
src/comm.c

File diff suppressed because it is too large Load Diff

View File

@ -17,21 +17,21 @@
enum op { MAX = 0, SUM }; enum op { MAX = 0, SUM };
typedef struct { typedef struct {
int rank; int rank;
int size; int size;
#if defined(_MPI) #if defined(_MPI)
MPI_Comm comm; MPI_Comm comm;
int num_external; int num_external;
int num_send_neighbors; int num_send_neighbors;
int* external_index; int* external_index;
int* external_local_index; int* external_local_index;
int total_to_be_sent; int total_to_be_sent;
int* elements_to_send; int* elements_to_send;
int neighbors[MAX_NUM_NEIGHBOURS]; int neighbors[MAX_NUM_NEIGHBOURS];
int recv_length[MAX_NUM_NEIGHBOURS]; int recv_length[MAX_NUM_NEIGHBOURS];
int send_length[MAX_NUM_NEIGHBOURS]; int send_length[MAX_NUM_NEIGHBOURS];
double* send_buffer; double* send_buffer;
#endif #endif
} Comm; } Comm;

View File

@ -17,100 +17,100 @@
CG_FLOAT compute_residual(Solver* s) CG_FLOAT compute_residual(Solver* s)
{ {
CG_FLOAT residual = 0.0; CG_FLOAT residual = 0.0;
int n = s->A.nr; int n = s->A.nr;
CG_FLOAT* v1 = s->x; CG_FLOAT* v1 = s->x;
CG_FLOAT* v2 = s->xexact; CG_FLOAT* v2 = s->xexact;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
double diff = fabs(v1[i] - v2[i]); double diff = fabs(v1[i] - v2[i]);
if (diff > residual) residual = diff; if (diff > residual) residual = diff;
} }
commReduction(&residual, MAX); commReduction(&residual, MAX);
return residual; return residual;
} }
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
double timeStart, timeStop; double timeStart, timeStop;
Parameter param; Parameter param;
Solver s; Solver s;
Comm comm; Comm comm;
commInit(&comm, argc, argv); commInit(&comm, argc, argv);
initParameter(&param); initParameter(&param);
if (argc != 2) { if (argc != 2) {
if (commIsMaster(&comm)) { if (commIsMaster(&comm)) {
printf("Usage: %s <configFile>\n", argv[0]); printf("Usage: %s <configFile>\n", argv[0]);
}
commFinalize(&comm);
exit(EXIT_SUCCESS);
} }
readParameter(&param, argv[1]);
CG_FLOAT eps = (CG_FLOAT)param.eps;
int itermax = param.itermax;
initSolver(&s, &comm, &param);
commMatrixDump(&comm, &s.A);
commFinalize(&comm); commFinalize(&comm);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
}
CG_UINT nrow = s.A.nr; readParameter(&param, argv[1]);
CG_UINT ncol = s.A.nc;
CG_FLOAT* r = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, nrow * sizeof(CG_FLOAT));
CG_FLOAT* p = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, ncol * sizeof(CG_FLOAT));
CG_FLOAT* Ap = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, nrow * sizeof(CG_FLOAT));
CG_FLOAT normr = 0.0;
CG_FLOAT rtrans = 0.0, oldrtrans;
waxpby(nrow, 1.0, s.x, 0.0, s.x, p); CG_FLOAT eps = (CG_FLOAT)param.eps;
spMVM(&s.A, p, Ap); int itermax = param.itermax;
waxpby(nrow, 1.0, s.b, -1.0, Ap, r); initSolver(&s, &comm, &param);
commMatrixDump(&comm, &s.A);
commFinalize(&comm);
exit(EXIT_SUCCESS);
CG_UINT nrow = s.A.nr;
CG_UINT ncol = s.A.nc;
CG_FLOAT* r = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, nrow * sizeof(CG_FLOAT));
CG_FLOAT* p = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, ncol * sizeof(CG_FLOAT));
CG_FLOAT* Ap = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, nrow * sizeof(CG_FLOAT));
CG_FLOAT normr = 0.0;
CG_FLOAT rtrans = 0.0, oldrtrans;
waxpby(nrow, 1.0, s.x, 0.0, s.x, p);
spMVM(&s.A, p, Ap);
waxpby(nrow, 1.0, s.b, -1.0, Ap, r);
ddot(nrow, r, r, &rtrans);
normr = sqrt(rtrans);
// initial iteration
waxpby(nrow, 1.0, r, 0.0, r, p);
commExchange(&comm, &s.A, p);
spMVM(&s.A, p, Ap);
double alpha = 0.0;
ddot(nrow, p, Ap, &alpha);
alpha = rtrans / alpha;
waxpby(nrow, 1.0, s.x, alpha, p, s.x);
waxpby(nrow, 1.0, r, -alpha, Ap, r);
int k;
timeStart = getTimeStamp();
for (k = 1; k < itermax && normr > eps; k++) {
oldrtrans = rtrans;
ddot(nrow, r, r, &rtrans); ddot(nrow, r, r, &rtrans);
double beta = rtrans / oldrtrans;
normr = sqrt(rtrans); waxpby(nrow, 1.0, r, beta, p, p);
// initial iteration
waxpby(nrow, 1.0, r, 0.0, r, p);
commExchange(&comm, &s.A, p); commExchange(&comm, &s.A, p);
spMVM(&s.A, p, Ap); spMVM(&s.A, p, Ap);
double alpha = 0.0; alpha = 0.0;
ddot(nrow, p, Ap, &alpha); ddot(nrow, p, Ap, &alpha);
alpha = rtrans / alpha; alpha = rtrans / alpha;
waxpby(nrow, 1.0, s.x, alpha, p, s.x); waxpby(nrow, 1.0, s.x, alpha, p, s.x);
waxpby(nrow, 1.0, r, -alpha, Ap, r); waxpby(nrow, 1.0, r, -alpha, Ap, r);
}
timeStop = getTimeStamp();
int k; double residual = compute_residual(&s);
timeStart = getTimeStamp();
for (k = 1; k < itermax && normr > eps; k++) {
oldrtrans = rtrans;
ddot(nrow, r, r, &rtrans);
double beta = rtrans / oldrtrans;
waxpby(nrow, 1.0, r, beta, p, p);
commExchange(&comm, &s.A, p);
spMVM(&s.A, p, Ap);
alpha = 0.0;
ddot(nrow, p, Ap, &alpha);
alpha = rtrans / alpha;
waxpby(nrow, 1.0, s.x, alpha, p, s.x);
waxpby(nrow, 1.0, r, -alpha, Ap, r);
}
timeStop = getTimeStamp();
double residual = compute_residual(&s); if (commIsMaster(&comm)) {
printf("Solution performed %d iterations and took %.2fs\n",
k,
timeStop - timeStart);
printf("Difference between computed and exact = %f\n", residual);
}
if (commIsMaster(&comm)) { commFinalize(&comm);
printf("Solution performed %d iterations and took %.2fs\n", return EXIT_SUCCESS;
k,
timeStop - timeStart);
printf("Difference between computed and exact = %f\n", residual);
}
commFinalize(&comm);
return EXIT_SUCCESS;
} }

View File

@ -15,154 +15,156 @@
static inline int compareColumn(const void* a, const void* b) static inline int compareColumn(const void* a, const void* b)
{ {
const Entry* a_ = (const Entry*)a; const Entry* a_ = (const Entry*)a;
const Entry* b_ = (const Entry*)b; const Entry* b_ = (const Entry*)b;
return (a_->col > b_->col) - (a_->col < b_->col); return (a_->col > b_->col) - (a_->col < b_->col);
} }
static inline int compareRow(const void* a, const void* b) static inline int compareRow(const void* a, const void* b)
{ {
const Entry* a_ = (const Entry*)a; const Entry* a_ = (const Entry*)a;
const Entry* b_ = (const Entry*)b; const Entry* b_ = (const Entry*)b;
return (a_->row > b_->row) - (a_->row < b_->row); return (a_->row > b_->row) - (a_->row < b_->row);
} }
static void dumpMMMatrix(Entry* mm, int nz) static void dumpMMMatrix(Entry* mm, int nz)
{ {
for (int i = 0; i < nz; i++) { for (int i = 0; i < nz; i++) {
printf("%d %d: %f\n", mm[i].row, mm[i].col, mm[i].val); printf("%d %d: %f\n", mm[i].row, mm[i].col, mm[i].val);
} }
} }
void matrixRead(Matrix* m, char* filename) void matrixRead(Matrix* m, char* filename)
{ {
MM_typecode matcode; MM_typecode matcode;
FILE* f; FILE* f;
int M, N, nz; int M, N, nz;
if ((f = fopen(filename, "r")) == NULL) { if ((f = fopen(filename, "r")) == NULL) {
printf("Unable to open file"); printf("Unable to open file");
}
if (mm_read_banner(f, &matcode) != 0) {
printf("Could not process Matrix Market banner.\n");
exit(EXIT_FAILURE);
}
if (!((mm_is_real(matcode) || mm_is_pattern(matcode) ||
mm_is_integer(matcode)) &&
mm_is_matrix(matcode) && mm_is_sparse(matcode))) {
fprintf(stderr, "Sorry, this application does not support ");
fprintf(stderr, "Market Market type: [%s]\n", mm_typecode_to_str(matcode));
exit(EXIT_FAILURE);
}
bool compatible_flag = (mm_is_sparse(matcode) &&
(mm_is_real(matcode) || mm_is_pattern(matcode) ||
mm_is_integer(matcode))) &&
(mm_is_symmetric(matcode) || mm_is_general(matcode));
bool sym_flag = mm_is_symmetric(matcode);
bool pattern_flag = mm_is_pattern(matcode);
bool complex_flag = mm_is_complex(matcode);
if (!compatible_flag) {
printf("The matrix market file provided is not supported.\n Reason :\n");
if (!mm_is_sparse(matcode)) {
printf(" * matrix has to be sparse\n");
} }
if (mm_read_banner(f, &matcode) != 0) { if (!mm_is_real(matcode) && !(mm_is_pattern(matcode))) {
printf("Could not process Matrix Market banner.\n"); printf(" * matrix has to be real or pattern\n");
exit(EXIT_FAILURE);
} }
if (!((mm_is_real(matcode) || mm_is_pattern(matcode) || mm_is_integer(matcode)) && if (!mm_is_symmetric(matcode) && !mm_is_general(matcode)) {
mm_is_matrix(matcode) && mm_is_sparse(matcode))) { printf(" * matrix has to be either general or symmetric\n");
fprintf(stderr, "Sorry, this application does not support ");
fprintf(stderr, "Market Market type: [%s]\n", mm_typecode_to_str(matcode));
exit(EXIT_FAILURE);
} }
bool compatible_flag = (mm_is_sparse(matcode) && exit(EXIT_FAILURE);
(mm_is_real(matcode) || mm_is_pattern(matcode) || }
mm_is_integer(matcode))) &&
(mm_is_symmetric(matcode) || mm_is_general(matcode));
bool sym_flag = mm_is_symmetric(matcode);
bool pattern_flag = mm_is_pattern(matcode);
bool complex_flag = mm_is_complex(matcode);
if (!compatible_flag) { if (mm_read_mtx_crd_size(f, &M, &N, &nz) != 0) {
printf("The matrix market file provided is not supported.\n Reason :\n"); exit(EXIT_FAILURE);
if (!mm_is_sparse(matcode)) { }
printf(" * matrix has to be sparse\n");
}
if (!mm_is_real(matcode) && !(mm_is_pattern(matcode))) { printf("Read matrix %s with %d non zeroes and %d rows\n", filename, nz, M);
printf(" * matrix has to be real or pattern\n");
}
if (!mm_is_symmetric(matcode) && !mm_is_general(matcode)) { m->nr = M;
printf(" * matrix has to be either general or symmetric\n"); m->nnz = nz;
} Entry* mm;
exit(EXIT_FAILURE); if (sym_flag) {
} mm = (Entry*)allocate(ARRAY_ALIGNMENT, nz * 2 * sizeof(Entry));
} else {
mm = (Entry*)allocate(ARRAY_ALIGNMENT, nz * sizeof(Entry));
}
if (mm_read_mtx_crd_size(f, &M, &N, &nz) != 0) { size_t cursor = 0;
exit(EXIT_FAILURE); int row, col;
} double v;
printf("Read matrix %s with %d non zeroes and %d rows\n", filename, nz, M); for (size_t i = 0; i < nz; i++) {
m->nr = M; if (pattern_flag) {
m->nnz = nz; fscanf(f, "%d %d\n", &row, &col);
Entry* mm; v = 1.;
} else if (complex_flag) {
if (sym_flag) { fscanf(f, "%d %d %lg %*g\n", &row, &col, &v);
mm = (Entry*)allocate(ARRAY_ALIGNMENT, nz * 2 * sizeof(Entry));
} else { } else {
mm = (Entry*)allocate(ARRAY_ALIGNMENT, nz * sizeof(Entry)); fscanf(f, "%d %d %lg\n", &row, &col, &v);
} }
size_t cursor = 0; row--; /* adjust from 1-based to 0-based */
int row, col; col--;
double v;
for (size_t i = 0; i < nz; i++) { mm[cursor].row = row;
mm[cursor].col = col;
mm[cursor++].val = v;
if (pattern_flag) { if (sym_flag && (row != col)) {
fscanf(f, "%d %d\n", &row, &col); mm[cursor].row = col;
v = 1.; mm[cursor].col = row;
} else if (complex_flag) { mm[cursor++].val = v;
fscanf(f, "%d %d %lg %*g\n", &row, &col, &v);
} else {
fscanf(f, "%d %d %lg\n", &row, &col, &v);
}
row--; /* adjust from 1-based to 0-based */
col--;
mm[cursor].row = row;
mm[cursor].col = col;
mm[cursor++].val = v;
if (sym_flag && (row != col)) {
mm[cursor].row = col;
mm[cursor].col = row;
mm[cursor++].val = v;
}
} }
}
fclose(f); fclose(f);
size_t mms = cursor; size_t mms = cursor;
// sort by column // sort by column
qsort(mm, mms, sizeof(Entry), compareColumn); qsort(mm, mms, sizeof(Entry), compareColumn);
// dumpMMMatrix(mm, nz); // dumpMMMatrix(mm, nz);
// sort by row // sort by row
mergesort(mm, mms, sizeof(Entry), compareRow); mergesort(mm, mms, sizeof(Entry), compareRow);
// dumpMMMatrix(mm, nz); // dumpMMMatrix(mm, nz);
m->rowPtr = (CG_UINT*)allocate(ARRAY_ALIGNMENT, (m->nr + 1) * sizeof(CG_UINT)); m->rowPtr = (CG_UINT*)allocate(ARRAY_ALIGNMENT,
m->colInd = (CG_UINT*)allocate(ARRAY_ALIGNMENT, m->nnz * sizeof(CG_UINT)); (m->nr + 1) * sizeof(CG_UINT));
m->val = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, m->nnz * sizeof(CG_FLOAT)); m->colInd = (CG_UINT*)allocate(ARRAY_ALIGNMENT, m->nnz * sizeof(CG_UINT));
m->val = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, m->nnz * sizeof(CG_FLOAT));
int* valsPerRow = (int*)allocate(ARRAY_ALIGNMENT, m->nr * sizeof(int)); int* valsPerRow = (int*)allocate(ARRAY_ALIGNMENT, m->nr * sizeof(int));
for (int i = 0; i < m->nr; i++) { for (int i = 0; i < m->nr; i++) {
valsPerRow[i] = 0; valsPerRow[i] = 0;
} }
for (int i = 0; i < mms; i++) { for (int i = 0; i < mms; i++) {
valsPerRow[mm[i].row]++; valsPerRow[mm[i].row]++;
} }
m->rowPtr[0] = 0; m->rowPtr[0] = 0;
// convert to CRS format // convert to CRS format
for (int rowID = 0; rowID < m->nr; rowID++) { for (int rowID = 0; rowID < m->nr; rowID++) {
m->rowPtr[rowID + 1] = m->rowPtr[rowID] + valsPerRow[rowID]; m->rowPtr[rowID + 1] = m->rowPtr[rowID] + valsPerRow[rowID];
// loop over all elements in Row // loop over all elements in Row
for (int id = m->rowPtr[rowID]; id < m->rowPtr[rowID + 1]; id++) { for (int id = m->rowPtr[rowID]; id < m->rowPtr[rowID + 1]; id++) {
m->val[id] = (CG_FLOAT)mm[id].val; m->val[id] = (CG_FLOAT)mm[id].val;
m->colInd[id] = (CG_UINT)mm[id].col; m->colInd[id] = (CG_UINT)mm[id].col;
}
} }
}
} }

View File

@ -9,17 +9,17 @@
#include "util.h" #include "util.h"
typedef struct { typedef struct {
int row; int row;
int col; int col;
double val; double val;
} Entry; } Entry;
typedef struct { typedef struct {
CG_UINT nr, nc, nnz; // number of rows, columns and non zeros CG_UINT nr, nc, nnz; // number of rows, columns and non zeros
CG_UINT totalNr, totalNnz; // number of rows and non zeros CG_UINT totalNr, totalNnz; // number of rows and non zeros
CG_UINT startRow, stopRow; CG_UINT startRow, stopRow;
CG_UINT *colInd, *rowPtr; // colum Indices, row Pointer CG_UINT *colInd, *rowPtr; // colum Indices, row Pointer
CG_FLOAT* val; CG_FLOAT* val;
} Matrix; } Matrix;
extern void matrixRead(Matrix* m, char* filename); extern void matrixRead(Matrix* m, char* filename);

View File

@ -11,206 +11,220 @@
#include "mmio.h" #include "mmio.h"
int mm_read_unsymmetric_sparse( int mm_read_unsymmetric_sparse(const char* fname,
const char* fname, int* M_, int* N_, int* nz_, double** val_, int** I_, int** J_) int* M_,
int* N_,
int* nz_,
double** val_,
int** I_,
int** J_)
{ {
FILE* f; FILE* f;
MM_typecode matcode; MM_typecode matcode;
int M, N, nz; int M, N, nz;
int i; int i;
double* val; double* val;
int *I, *J; int *I, *J;
if ((f = fopen(fname, "r")) == NULL) return -1; if ((f = fopen(fname, "r")) == NULL) return -1;
if (mm_read_banner(f, &matcode) != 0) { if (mm_read_banner(f, &matcode) != 0) {
printf("mm_read_unsymetric: Could not process Matrix Market banner "); printf("mm_read_unsymetric: Could not process Matrix Market banner ");
printf(" in file [%s]\n", fname); printf(" in file [%s]\n", fname);
return -1; return -1;
} }
if (!(mm_is_real(matcode) && mm_is_matrix(matcode) && mm_is_sparse(matcode))) { if (!(mm_is_real(matcode) && mm_is_matrix(matcode) &&
fprintf(stderr, "Sorry, this application does not support "); mm_is_sparse(matcode))) {
fprintf(stderr, "Market Market type: [%s]\n", mm_typecode_to_str(matcode)); fprintf(stderr, "Sorry, this application does not support ");
return -1; fprintf(stderr, "Market Market type: [%s]\n", mm_typecode_to_str(matcode));
} return -1;
}
/* find out size of sparse matrix: M, N, nz .... */ /* find out size of sparse matrix: M, N, nz .... */
if (mm_read_mtx_crd_size(f, &M, &N, &nz) != 0) { if (mm_read_mtx_crd_size(f, &M, &N, &nz) != 0) {
fprintf(stderr, "read_unsymmetric_sparse(): could not parse matrix size.\n"); fprintf(stderr,
return -1; "read_unsymmetric_sparse(): could not parse matrix size.\n");
} return -1;
}
*M_ = M; *M_ = M;
*N_ = N; *N_ = N;
*nz_ = nz; *nz_ = nz;
/* reseve memory for matrices */ /* reseve memory for matrices */
I = (int*)malloc(nz * sizeof(int)); I = (int*)malloc(nz * sizeof(int));
J = (int*)malloc(nz * sizeof(int)); J = (int*)malloc(nz * sizeof(int));
val = (double*)malloc(nz * sizeof(double)); val = (double*)malloc(nz * sizeof(double));
*val_ = val; *val_ = val;
*I_ = I; *I_ = I;
*J_ = J; *J_ = J;
/* NOTE: when reading in doubles, ANSI C requires the use of the "l" */ /* NOTE: when reading in doubles, ANSI C requires the use of the "l" */
/* specifier as in "%lg", "%lf", "%le", otherwise errors will occur */ /* specifier as in "%lg", "%lf", "%le", otherwise errors will occur */
/* (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15) */ /* (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15) */
for (i = 0; i < nz; i++) { for (i = 0; i < nz; i++) {
fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]); fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]);
I[i]--; /* adjust from 1-based to 0-based */ I[i]--; /* adjust from 1-based to 0-based */
J[i]--; J[i]--;
} }
fclose(f); fclose(f);
return 0; return 0;
} }
int mm_is_valid(MM_typecode matcode) int mm_is_valid(MM_typecode matcode)
{ {
if (!mm_is_matrix(matcode)) return 0; if (!mm_is_matrix(matcode)) return 0;
if (mm_is_dense(matcode) && mm_is_pattern(matcode)) return 0; if (mm_is_dense(matcode) && mm_is_pattern(matcode)) return 0;
if (mm_is_real(matcode) && mm_is_hermitian(matcode)) return 0; if (mm_is_real(matcode) && mm_is_hermitian(matcode)) return 0;
if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) || mm_is_skew(matcode))) if (mm_is_pattern(matcode) &&
return 0; (mm_is_hermitian(matcode) || mm_is_skew(matcode)))
return 1; return 0;
return 1;
} }
int mm_read_banner(FILE* f, MM_typecode* matcode) int mm_read_banner(FILE* f, MM_typecode* matcode)
{ {
char line[MM_MAX_LINE_LENGTH]; char line[MM_MAX_LINE_LENGTH];
char banner[MM_MAX_TOKEN_LENGTH]; char banner[MM_MAX_TOKEN_LENGTH];
char mtx[MM_MAX_TOKEN_LENGTH]; char mtx[MM_MAX_TOKEN_LENGTH];
char crd[MM_MAX_TOKEN_LENGTH]; char crd[MM_MAX_TOKEN_LENGTH];
char data_type[MM_MAX_TOKEN_LENGTH]; char data_type[MM_MAX_TOKEN_LENGTH];
char storage_scheme[MM_MAX_TOKEN_LENGTH]; char storage_scheme[MM_MAX_TOKEN_LENGTH];
char* p; char* p;
mm_clear_typecode(matcode); mm_clear_typecode(matcode);
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) return MM_PREMATURE_EOF; if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) return MM_PREMATURE_EOF;
if (sscanf(line, "%s %s %s %s %s", banner, mtx, crd, data_type, storage_scheme) != 5) if (sscanf(line,
return MM_PREMATURE_EOF; "%s %s %s %s %s",
banner,
mtx,
crd,
data_type,
storage_scheme) != 5)
return MM_PREMATURE_EOF;
for (p = mtx; *p != '\0'; *p = tolower(*p), p++) for (p = mtx; *p != '\0'; *p = tolower(*p), p++)
; /* convert to lower case */ ; /* convert to lower case */
for (p = crd; *p != '\0'; *p = tolower(*p), p++) for (p = crd; *p != '\0'; *p = tolower(*p), p++)
; ;
for (p = data_type; *p != '\0'; *p = tolower(*p), p++) for (p = data_type; *p != '\0'; *p = tolower(*p), p++)
; ;
for (p = storage_scheme; *p != '\0'; *p = tolower(*p), p++) for (p = storage_scheme; *p != '\0'; *p = tolower(*p), p++)
; ;
/* check for banner */ /* check for banner */
if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0) if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0)
return MM_NO_HEADER; return MM_NO_HEADER;
/* first field should be "mtx" */ /* first field should be "mtx" */
if (strcmp(mtx, MM_MTX_STR) != 0) return MM_UNSUPPORTED_TYPE; if (strcmp(mtx, MM_MTX_STR) != 0) return MM_UNSUPPORTED_TYPE;
mm_set_matrix(matcode); mm_set_matrix(matcode);
/* second field describes whether this is a sparse matrix (in coordinate /* second field describes whether this is a sparse matrix (in coordinate
storgae) or a dense array */ storgae) or a dense array */
if (strcmp(crd, MM_SPARSE_STR) == 0) mm_set_sparse(matcode); if (strcmp(crd, MM_SPARSE_STR) == 0) mm_set_sparse(matcode);
else if (strcmp(crd, MM_DENSE_STR) == 0) else if (strcmp(crd, MM_DENSE_STR) == 0)
mm_set_dense(matcode); mm_set_dense(matcode);
else else
return MM_UNSUPPORTED_TYPE; return MM_UNSUPPORTED_TYPE;
/* third field */ /* third field */
if (strcmp(data_type, MM_REAL_STR) == 0) mm_set_real(matcode); if (strcmp(data_type, MM_REAL_STR) == 0) mm_set_real(matcode);
else if (strcmp(data_type, MM_COMPLEX_STR) == 0) else if (strcmp(data_type, MM_COMPLEX_STR) == 0)
mm_set_complex(matcode); mm_set_complex(matcode);
else if (strcmp(data_type, MM_PATTERN_STR) == 0) else if (strcmp(data_type, MM_PATTERN_STR) == 0)
mm_set_pattern(matcode); mm_set_pattern(matcode);
else if (strcmp(data_type, MM_INT_STR) == 0) else if (strcmp(data_type, MM_INT_STR) == 0)
mm_set_integer(matcode); mm_set_integer(matcode);
else else
return MM_UNSUPPORTED_TYPE; return MM_UNSUPPORTED_TYPE;
/* fourth field */ /* fourth field */
if (strcmp(storage_scheme, MM_GENERAL_STR) == 0) mm_set_general(matcode); if (strcmp(storage_scheme, MM_GENERAL_STR) == 0) mm_set_general(matcode);
else if (strcmp(storage_scheme, MM_SYMM_STR) == 0) else if (strcmp(storage_scheme, MM_SYMM_STR) == 0)
mm_set_symmetric(matcode); mm_set_symmetric(matcode);
else if (strcmp(storage_scheme, MM_HERM_STR) == 0) else if (strcmp(storage_scheme, MM_HERM_STR) == 0)
mm_set_hermitian(matcode); mm_set_hermitian(matcode);
else if (strcmp(storage_scheme, MM_SKEW_STR) == 0) else if (strcmp(storage_scheme, MM_SKEW_STR) == 0)
mm_set_skew(matcode); mm_set_skew(matcode);
else else
return MM_UNSUPPORTED_TYPE; return MM_UNSUPPORTED_TYPE;
return 0; return 0;
} }
int mm_write_mtx_crd_size(FILE* f, int M, int N, int nz) int mm_write_mtx_crd_size(FILE* f, int M, int N, int nz)
{ {
if (fprintf(f, "%d %d %d\n", M, N, nz) != 3) return MM_COULD_NOT_WRITE_FILE; if (fprintf(f, "%d %d %d\n", M, N, nz) != 3) return MM_COULD_NOT_WRITE_FILE;
else else
return 0; return 0;
} }
int mm_read_mtx_crd_size(FILE* f, int* M, int* N, int* nz) int mm_read_mtx_crd_size(FILE* f, int* M, int* N, int* nz)
{ {
char line[MM_MAX_LINE_LENGTH]; char line[MM_MAX_LINE_LENGTH];
int num_items_read; int num_items_read;
/* set return null parameter values, in case we exit with errors */ /* set return null parameter values, in case we exit with errors */
*M = *N = *nz = 0; *M = *N = *nz = 0;
/* now continue scanning until you reach the end-of-comments */ /* now continue scanning until you reach the end-of-comments */
do {
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) return MM_PREMATURE_EOF;
} while (line[0] == '%');
/* line[] is either blank or has M,N, nz */
if (sscanf(line, "%d %d %d", M, N, nz) == 3) return 0;
else
do { do {
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) return MM_PREMATURE_EOF; num_items_read = fscanf(f, "%d %d %d", M, N, nz);
} while (line[0] == '%'); if (num_items_read == EOF) return MM_PREMATURE_EOF;
} while (num_items_read != 3);
/* line[] is either blank or has M,N, nz */ return 0;
if (sscanf(line, "%d %d %d", M, N, nz) == 3) return 0;
else
do {
num_items_read = fscanf(f, "%d %d %d", M, N, nz);
if (num_items_read == EOF) return MM_PREMATURE_EOF;
} while (num_items_read != 3);
return 0;
} }
int mm_read_mtx_array_size(FILE* f, int* M, int* N) int mm_read_mtx_array_size(FILE* f, int* M, int* N)
{ {
char line[MM_MAX_LINE_LENGTH]; char line[MM_MAX_LINE_LENGTH];
int num_items_read; int num_items_read;
/* set return null parameter values, in case we exit with errors */ /* set return null parameter values, in case we exit with errors */
*M = *N = 0; *M = *N = 0;
/* now continue scanning until you reach the end-of-comments */ /* now continue scanning until you reach the end-of-comments */
do {
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) return MM_PREMATURE_EOF;
} while (line[0] == '%');
/* line[] is either blank or has M,N, nz */
if (sscanf(line, "%d %d", M, N) == 2) return 0;
else /* we have a blank line */
do { do {
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) return MM_PREMATURE_EOF; num_items_read = fscanf(f, "%d %d", M, N);
} while (line[0] == '%'); if (num_items_read == EOF) return MM_PREMATURE_EOF;
} while (num_items_read != 2);
/* line[] is either blank or has M,N, nz */ return 0;
if (sscanf(line, "%d %d", M, N) == 2) return 0;
else /* we have a blank line */
do {
num_items_read = fscanf(f, "%d %d", M, N);
if (num_items_read == EOF) return MM_PREMATURE_EOF;
} while (num_items_read != 2);
return 0;
} }
int mm_write_mtx_array_size(FILE* f, int M, int N) int mm_write_mtx_array_size(FILE* f, int M, int N)
{ {
if (fprintf(f, "%d %d\n", M, N) != 2) return MM_COULD_NOT_WRITE_FILE; if (fprintf(f, "%d %d\n", M, N) != 2) return MM_COULD_NOT_WRITE_FILE;
else else
return 0; return 0;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -219,47 +233,58 @@ int mm_write_mtx_array_size(FILE* f, int M, int N)
/* use when I[], J[], and val[]J, and val[] are already allocated */ /* use when I[], J[], and val[]J, and val[] are already allocated */
/******************************************************************/ /******************************************************************/
int mm_read_mtx_crd_data( int mm_read_mtx_crd_data(FILE* f,
FILE* f, int M, int N, int nz, int I[], int J[], double val[], MM_typecode matcode) int M,
int N,
int nz,
int I[],
int J[],
double val[],
MM_typecode matcode)
{ {
int i; int i;
if (mm_is_complex(matcode)) { if (mm_is_complex(matcode)) {
for (i = 0; i < nz; i++) for (i = 0; i < nz; i++)
if (fscanf(f, "%d %d %lg %lg", &I[i], &J[i], &val[2 * i], &val[2 * i + 1]) != if (fscanf(f,
4) "%d %d %lg %lg",
return MM_PREMATURE_EOF; &I[i],
} else if (mm_is_real(matcode)) { &J[i],
for (i = 0; i < nz; i++) { &val[2 * i],
if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]) != 3) &val[2 * i + 1]) != 4)
return MM_PREMATURE_EOF; return MM_PREMATURE_EOF;
} } else if (mm_is_real(matcode)) {
for (i = 0; i < nz; i++) {
if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]) != 3)
return MM_PREMATURE_EOF;
} }
}
else if (mm_is_pattern(matcode)) { else if (mm_is_pattern(matcode)) {
for (i = 0; i < nz; i++) for (i = 0; i < nz; i++)
if (fscanf(f, "%d %d", &I[i], &J[i]) != 2) return MM_PREMATURE_EOF; if (fscanf(f, "%d %d", &I[i], &J[i]) != 2) return MM_PREMATURE_EOF;
} else } else
return MM_UNSUPPORTED_TYPE; return MM_UNSUPPORTED_TYPE;
return 0; return 0;
} }
int mm_read_mtx_crd_entry( int mm_read_mtx_crd_entry(
FILE* f, int* I, int* J, double* real, double* imag, MM_typecode matcode) FILE* f, int* I, int* J, double* real, double* imag, MM_typecode matcode)
{ {
if (mm_is_complex(matcode)) { if (mm_is_complex(matcode)) {
if (fscanf(f, "%d %d %lg %lg", I, J, real, imag) != 4) return MM_PREMATURE_EOF; if (fscanf(f, "%d %d %lg %lg", I, J, real, imag) != 4)
} else if (mm_is_real(matcode)) { return MM_PREMATURE_EOF;
if (fscanf(f, "%d %d %lg\n", I, J, real) != 3) return MM_PREMATURE_EOF; } else if (mm_is_real(matcode)) {
if (fscanf(f, "%d %d %lg\n", I, J, real) != 3) return MM_PREMATURE_EOF;
} }
else if (mm_is_pattern(matcode)) { else if (mm_is_pattern(matcode)) {
if (fscanf(f, "%d %d", I, J) != 2) return MM_PREMATURE_EOF; if (fscanf(f, "%d %d", I, J) != 2) return MM_PREMATURE_EOF;
} else } else
return MM_UNSUPPORTED_TYPE; return MM_UNSUPPORTED_TYPE;
return 0; return 0;
} }
/************************************************************************ /************************************************************************
@ -279,53 +304,54 @@ int mm_read_mtx_crd(char* fname,
double** val, double** val,
MM_typecode* matcode) MM_typecode* matcode)
{ {
int ret_code; int ret_code;
FILE* f; FILE* f;
if (strcmp(fname, "stdin") == 0) f = stdin; if (strcmp(fname, "stdin") == 0) f = stdin;
else if ((f = fopen(fname, "r")) == NULL) else if ((f = fopen(fname, "r")) == NULL)
return MM_COULD_NOT_READ_FILE; return MM_COULD_NOT_READ_FILE;
if ((ret_code = mm_read_banner(f, matcode)) != 0) return ret_code; if ((ret_code = mm_read_banner(f, matcode)) != 0) return ret_code;
if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) && mm_is_matrix(*matcode))) if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) &&
return MM_UNSUPPORTED_TYPE; mm_is_matrix(*matcode)))
return MM_UNSUPPORTED_TYPE;
if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0) return ret_code; if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0) return ret_code;
*I = (int*)malloc(*nz * sizeof(int)); *I = (int*)malloc(*nz * sizeof(int));
*J = (int*)malloc(*nz * sizeof(int)); *J = (int*)malloc(*nz * sizeof(int));
*val = NULL; *val = NULL;
if (mm_is_complex(*matcode)) { if (mm_is_complex(*matcode)) {
*val = (double*)malloc(*nz * 2 * sizeof(double)); *val = (double*)malloc(*nz * 2 * sizeof(double));
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, *matcode); ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, *matcode);
if (ret_code != 0) return ret_code; if (ret_code != 0) return ret_code;
} else if (mm_is_real(*matcode)) { } else if (mm_is_real(*matcode)) {
*val = (double*)malloc(*nz * sizeof(double)); *val = (double*)malloc(*nz * sizeof(double));
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, *matcode); ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, *matcode);
if (ret_code != 0) return ret_code; if (ret_code != 0) return ret_code;
} }
else if (mm_is_pattern(*matcode)) { else if (mm_is_pattern(*matcode)) {
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, *matcode); ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, *matcode);
if (ret_code != 0) return ret_code; if (ret_code != 0) return ret_code;
} }
if (f != stdin) fclose(f); if (f != stdin) fclose(f);
return 0; return 0;
} }
int mm_write_banner(FILE* f, MM_typecode matcode) int mm_write_banner(FILE* f, MM_typecode matcode)
{ {
char* str = mm_typecode_to_str(matcode); char* str = mm_typecode_to_str(matcode);
int ret_code; int ret_code;
ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, str); ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, str);
free(str); free(str);
if (ret_code != 2) return MM_COULD_NOT_WRITE_FILE; if (ret_code != 2) return MM_COULD_NOT_WRITE_FILE;
else else
return 0; return 0;
} }
int mm_write_mtx_crd(char fname[], int mm_write_mtx_crd(char fname[],
@ -337,38 +363,43 @@ int mm_write_mtx_crd(char fname[],
double val[], double val[],
MM_typecode matcode) MM_typecode matcode)
{ {
FILE* f; FILE* f;
int i; int i;
if (strcmp(fname, "stdout") == 0) f = stdout; if (strcmp(fname, "stdout") == 0) f = stdout;
else if ((f = fopen(fname, "w")) == NULL) else if ((f = fopen(fname, "w")) == NULL)
return MM_COULD_NOT_WRITE_FILE; return MM_COULD_NOT_WRITE_FILE;
/* print banner followed by typecode */ /* print banner followed by typecode */
fprintf(f, "%s ", MatrixMarketBanner); fprintf(f, "%s ", MatrixMarketBanner);
fprintf(f, "%s\n", mm_typecode_to_str(matcode)); fprintf(f, "%s\n", mm_typecode_to_str(matcode));
/* print matrix sizes and nonzeros */ /* print matrix sizes and nonzeros */
fprintf(f, "%d %d %d\n", M, N, nz); fprintf(f, "%d %d %d\n", M, N, nz);
/* print values */
if (mm_is_pattern(matcode))
for (i = 0; i < nz; i++)
fprintf(f, "%d %d\n", I[i], J[i]);
else if (mm_is_real(matcode))
for (i = 0; i < nz; i++)
fprintf(f, "%d %d %20.16g\n", I[i], J[i], val[i]);
else if (mm_is_complex(matcode))
for (i = 0; i < nz; i++)
fprintf(f, "%d %d %20.16g %20.16g\n", I[i], J[i], val[2 * i], val[2 * i + 1]);
else {
if (f != stdout) fclose(f);
return MM_UNSUPPORTED_TYPE;
}
/* print values */
if (mm_is_pattern(matcode))
for (i = 0; i < nz; i++)
fprintf(f, "%d %d\n", I[i], J[i]);
else if (mm_is_real(matcode))
for (i = 0; i < nz; i++)
fprintf(f, "%d %d %20.16g\n", I[i], J[i], val[i]);
else if (mm_is_complex(matcode))
for (i = 0; i < nz; i++)
fprintf(f,
"%d %d %20.16g %20.16g\n",
I[i],
J[i],
val[2 * i],
val[2 * i + 1]);
else {
if (f != stdout) fclose(f); if (f != stdout) fclose(f);
return MM_UNSUPPORTED_TYPE;
}
return 0; if (f != stdout) fclose(f);
return 0;
} }
/** /**
@ -378,52 +409,52 @@ int mm_write_mtx_crd(char fname[],
*/ */
char* mm_strdup(const char* s) char* mm_strdup(const char* s)
{ {
int len = strlen(s); int len = strlen(s);
char* s2 = (char*)malloc((len + 1) * sizeof(char)); char* s2 = (char*)malloc((len + 1) * sizeof(char));
return strcpy(s2, s); return strcpy(s2, s);
} }
char* mm_typecode_to_str(MM_typecode matcode) char* mm_typecode_to_str(MM_typecode matcode)
{ {
char buffer[MM_MAX_LINE_LENGTH]; char buffer[MM_MAX_LINE_LENGTH];
char* types[4]; char* types[4];
char* mm_strdup(const char*); char* mm_strdup(const char*);
int error = 0; int error = 0;
/* check for MTX type */ /* check for MTX type */
if (mm_is_matrix(matcode)) types[0] = MM_MTX_STR; if (mm_is_matrix(matcode)) types[0] = MM_MTX_STR;
else else
error = 1; error = 1;
/* check for CRD or ARR matrix */ /* check for CRD or ARR matrix */
if (mm_is_sparse(matcode)) types[1] = MM_SPARSE_STR; if (mm_is_sparse(matcode)) types[1] = MM_SPARSE_STR;
else if (mm_is_dense(matcode)) else if (mm_is_dense(matcode))
types[1] = MM_DENSE_STR; types[1] = MM_DENSE_STR;
else else
return NULL; return NULL;
/* check for element data type */ /* check for element data type */
if (mm_is_real(matcode)) types[2] = MM_REAL_STR; if (mm_is_real(matcode)) types[2] = MM_REAL_STR;
else if (mm_is_complex(matcode)) else if (mm_is_complex(matcode))
types[2] = MM_COMPLEX_STR; types[2] = MM_COMPLEX_STR;
else if (mm_is_pattern(matcode)) else if (mm_is_pattern(matcode))
types[2] = MM_PATTERN_STR; types[2] = MM_PATTERN_STR;
else if (mm_is_integer(matcode)) else if (mm_is_integer(matcode))
types[2] = MM_INT_STR; types[2] = MM_INT_STR;
else else
return NULL; return NULL;
/* check for symmetry type */ /* check for symmetry type */
if (mm_is_general(matcode)) types[3] = MM_GENERAL_STR; if (mm_is_general(matcode)) types[3] = MM_GENERAL_STR;
else if (mm_is_symmetric(matcode)) else if (mm_is_symmetric(matcode))
types[3] = MM_SYMM_STR; types[3] = MM_SYMM_STR;
else if (mm_is_hermitian(matcode)) else if (mm_is_hermitian(matcode))
types[3] = MM_HERM_STR; types[3] = MM_HERM_STR;
else if (mm_is_skew(matcode)) else if (mm_is_skew(matcode))
types[3] = MM_SKEW_STR; types[3] = MM_SKEW_STR;
else else
return NULL; return NULL;
sprintf(buffer, "%s %s %s %s", types[0], types[1], types[2], types[3]); sprintf(buffer, "%s %s %s %s", types[0], types[1], types[2], types[3]);
return mm_strdup(buffer); return mm_strdup(buffer);
} }

View File

@ -64,8 +64,8 @@ int mm_is_valid(MM_typecode matcode); /* too complex for a macro */
#define mm_set_skew(typecode) ((*typecode)[3] = 'K') #define mm_set_skew(typecode) ((*typecode)[3] = 'K')
#define mm_set_hermitian(typecode) ((*typecode)[3] = 'H') #define mm_set_hermitian(typecode) ((*typecode)[3] = 'H')
#define mm_clear_typecode(typecode) \ #define mm_clear_typecode(typecode) \
((*typecode)[0] = (*typecode)[1] = (*typecode)[2] = ' ', (*typecode)[3] = 'G') ((*typecode)[0] = (*typecode)[1] = (*typecode)[2] = ' ', (*typecode)[3] = 'G')
#define mm_initialize_typecode(typecode) mm_clear_typecode(typecode) #define mm_initialize_typecode(typecode) mm_clear_typecode(typecode)
@ -83,14 +83,14 @@ int mm_is_valid(MM_typecode matcode); /* too complex for a macro */
MM_matrix_typecode: 4-character sequence MM_matrix_typecode: 4-character sequence
ojbect sparse/ data storage dense ojbect sparse/ data
type scheme storage dense type scheme
string position: [0] [1] [2] [3] string position: [0] [1] [2] [3]
Matrix typecode: M(atrix) C(oord) R(eal) G(eneral) Matrix typecode: M(atrix) C(oord) R(eal) G(eneral)
A(array) C(omplex) A(array)
H(ermitian) P(attern) S(ymmetric) I(nteger) K(kew) C(omplex) H(ermitian) P(attern) S(ymmetric) I(nteger) K(kew)
***********************************************************************/ ***********************************************************************/
@ -118,12 +118,23 @@ int mm_write_mtx_crd(char fname[],
int J[], int J[],
double val[], double val[],
MM_typecode matcode); MM_typecode matcode);
int mm_read_mtx_crd_data( int mm_read_mtx_crd_data(FILE* f,
FILE* f, int M, int N, int nz, int I[], int J[], double val[], MM_typecode matcode); int M,
int N,
int nz,
int I[],
int J[],
double val[],
MM_typecode matcode);
int mm_read_mtx_crd_entry( int mm_read_mtx_crd_entry(
FILE* f, int* I, int* J, double* real, double* img, MM_typecode matcode); FILE* f, int* I, int* J, double* real, double* img, MM_typecode matcode);
int mm_read_unsymmetric_sparse( int mm_read_unsymmetric_sparse(const char* fname,
const char* fname, int* M_, int* N_, int* nz_, double** val_, int** I_, int** J_); int* M_,
int* N_,
int* nz_,
double** val_,
int** I_,
int** J_);
#endif #endif

View File

@ -11,61 +11,61 @@
void initParameter(Parameter* param) void initParameter(Parameter* param)
{ {
param->filename = "generate"; param->filename = "generate";
param->nx = 100; param->nx = 100;
param->ny = 100; param->ny = 100;
param->nz = 1000; param->nz = 1000;
param->itermax = 1000; param->itermax = 1000;
param->eps = 0.0001; param->eps = 0.0001;
} }
void readParameter(Parameter* param, const char* filename) void readParameter(Parameter* param, const char* filename)
{ {
FILE* fp = fopen(filename, "r"); FILE* fp = fopen(filename, "r");
char line[MAXLINE]; char line[MAXLINE];
int i; int i;
if (!fp) { if (!fp) {
fprintf(stderr, "Could not open parameter file: %s\n", filename); fprintf(stderr, "Could not open parameter file: %s\n", filename);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
while (!feof(fp)) { while (!feof(fp)) {
line[0] = '\0'; line[0] = '\0';
fgets(line, MAXLINE, fp); fgets(line, MAXLINE, fp);
for (i = 0; line[i] != '\0' && line[i] != '#'; i++) for (i = 0; line[i] != '\0' && line[i] != '#'; i++)
; ;
line[i] = '\0'; line[i] = '\0';
char* tok = strtok(line, " "); char* tok = strtok(line, " ");
char* val = strtok(NULL, " "); char* val = strtok(NULL, " ");
#define PARSE_PARAM(p, f) \ #define PARSE_PARAM(p, f) \
if (strncmp(tok, #p, sizeof(#p) / sizeof(#p[0]) - 1) == 0) { \ if (strncmp(tok, #p, sizeof(#p) / sizeof(#p[0]) - 1) == 0) { \
param->p = f(val); \ param->p = f(val); \
} }
#define PARSE_STRING(p) PARSE_PARAM(p, strdup) #define PARSE_STRING(p) PARSE_PARAM(p, strdup)
#define PARSE_INT(p) PARSE_PARAM(p, atoi) #define PARSE_INT(p) PARSE_PARAM(p, atoi)
#define PARSE_REAL(p) PARSE_PARAM(p, atof) #define PARSE_REAL(p) PARSE_PARAM(p, atof)
if (tok != NULL && val != NULL) { if (tok != NULL && val != NULL) {
PARSE_INT(nx); PARSE_INT(nx);
PARSE_INT(ny); PARSE_INT(ny);
PARSE_INT(nz); PARSE_INT(nz);
PARSE_INT(itermax); PARSE_INT(itermax);
PARSE_REAL(eps); PARSE_REAL(eps);
}
} }
}
fclose(fp); fclose(fp);
} }
void printParameter(Parameter* param) void printParameter(Parameter* param)
{ {
printf("Parameters\n"); printf("Parameters\n");
printf("Geometry data:\n"); printf("Geometry data:\n");
printf("\tPoints (x, y, z): %d, %d, %d\n", param->nx, param->ny, param->nz); printf("\tPoints (x, y, z): %d, %d, %d\n", param->nx, param->ny, param->nz);
printf("Iterative solver parameters:\n"); printf("Iterative solver parameters:\n");
printf("\tMax iterations: %d\n", param->itermax); printf("\tMax iterations: %d\n", param->itermax);
printf("\tepsilon (stopping tolerance) : %f\n", param->eps); printf("\tepsilon (stopping tolerance) : %f\n", param->eps);
} }

View File

@ -6,10 +6,10 @@
#define __PARAMETER_H_ #define __PARAMETER_H_
typedef struct { typedef struct {
char* filename; char* filename;
int nx, ny, nz; int nx, ny, nz;
int itermax; int itermax;
double eps; double eps;
} Parameter; } Parameter;
void initParameter(Parameter*); void initParameter(Parameter*);

View File

@ -13,36 +13,36 @@ static int _current;
void initProgress(double end) void initProgress(double end)
{ {
_end = end; _end = end;
_current = 0; _current = 0;
printf("[ ]"); printf("[ ]");
fflush(stdout); fflush(stdout);
} }
void printProgress(double current) void printProgress(double current)
{ {
int new = (int)rint((current / _end) * 10.0); int new = (int)rint((current / _end) * 10.0);
if (new > _current) { if (new > _current) {
char progress[11]; char progress[11];
_current = new; _current = new;
progress[0] = 0; progress[0] = 0;
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
if (i < _current) { if (i < _current) {
sprintf(progress + strlen(progress), "#"); sprintf(progress + strlen(progress), "#");
} else { } else {
sprintf(progress + strlen(progress), " "); sprintf(progress + strlen(progress), " ");
} }
}
printf("\r[%s]", progress);
} }
fflush(stdout); printf("\r[%s]", progress);
}
fflush(stdout);
} }
void stopProgress() void stopProgress()
{ {
printf("\n"); printf("\n");
fflush(stdout); fflush(stdout);
} }

View File

@ -13,139 +13,143 @@
#include "solver.h" #include "solver.h"
#include "util.h" #include "util.h"
static void matrixGenerate(Parameter* p, Solver* s, Comm* c, bool use_7pt_stencil) static void matrixGenerate(
Parameter* p, Solver* s, Comm* c, bool use_7pt_stencil)
{ {
int size = c->size; int size = c->size;
int rank = c->rank; int rank = c->rank;
CG_UINT local_nrow = p->nx * p->ny * p->nz; CG_UINT local_nrow = p->nx * p->ny * p->nz;
CG_UINT local_nnz = 27 * local_nrow; CG_UINT local_nnz = 27 * local_nrow;
CG_UINT total_nrow = local_nrow * size; CG_UINT total_nrow = local_nrow * size;
CG_UINT total_nnz = 27 * total_nrow; CG_UINT total_nnz = 27 * total_nrow;
int start_row = local_nrow * rank; int start_row = local_nrow * rank;
int stop_row = start_row + local_nrow - 1; int stop_row = start_row + local_nrow - 1;
if (commIsMaster(c)) { if (commIsMaster(c)) {
if (use_7pt_stencil) { if (use_7pt_stencil) {
printf("Generate 7pt matrix with "); printf("Generate 7pt matrix with ");
} else { } else {
printf("Generate 27pt matrix with "); printf("Generate 27pt matrix with ");
}
printf("%d total rows and %d nonzeros\n", (int)total_nrow, (int)local_nnz);
} }
printf("%d total rows and %d nonzeros\n", (int)total_nrow, (int)local_nnz);
}
s->A.val = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, local_nnz * sizeof(CG_FLOAT)); s->A.val = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, local_nnz * sizeof(CG_FLOAT));
s->A.colInd = (CG_UINT*)allocate(ARRAY_ALIGNMENT, local_nnz * sizeof(CG_UINT)); s->A.colInd = (CG_UINT*)allocate(ARRAY_ALIGNMENT,
s->A.rowPtr = (CG_UINT*)allocate(ARRAY_ALIGNMENT, (local_nrow + 1) * sizeof(CG_UINT)); local_nnz * sizeof(CG_UINT));
s->x = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, local_nrow * sizeof(CG_FLOAT)); s->A.rowPtr = (CG_UINT*)allocate(ARRAY_ALIGNMENT,
s->b = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, local_nrow * sizeof(CG_FLOAT)); (local_nrow + 1) * sizeof(CG_UINT));
s->xexact = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, local_nrow * sizeof(CG_FLOAT)); s->x = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, local_nrow * sizeof(CG_FLOAT));
s->b = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT, local_nrow * sizeof(CG_FLOAT));
s->xexact = (CG_FLOAT*)allocate(ARRAY_ALIGNMENT,
local_nrow * sizeof(CG_FLOAT));
CG_FLOAT* curvalptr = s->A.val; CG_FLOAT* curvalptr = s->A.val;
CG_UINT* curindptr = s->A.colInd; CG_UINT* curindptr = s->A.colInd;
CG_UINT* currowptr = s->A.rowPtr; CG_UINT* currowptr = s->A.rowPtr;
CG_FLOAT* x = s->x; CG_FLOAT* x = s->x;
CG_FLOAT* b = s->b; CG_FLOAT* b = s->b;
CG_FLOAT* xexact = s->xexact; CG_FLOAT* xexact = s->xexact;
CG_UINT nnzglobal = 0; CG_UINT nnzglobal = 0;
int nx = p->nx, ny = p->ny, nz = p->nz; int nx = p->nx, ny = p->ny, nz = p->nz;
CG_UINT cursor = 0; CG_UINT cursor = 0;
*currowptr++ = 0; *currowptr++ = 0;
for (int iz = 0; iz < nz; iz++) { for (int iz = 0; iz < nz; iz++) {
for (int iy = 0; iy < ny; iy++) { for (int iy = 0; iy < ny; iy++) {
for (int ix = 0; ix < nx; ix++) { for (int ix = 0; ix < nx; ix++) {
int curlocalrow = iz * nx * ny + iy * nx + ix; int curlocalrow = iz * nx * ny + iy * nx + ix;
int currow = start_row + iz * nx * ny + iy * nx + ix; int currow = start_row + iz * nx * ny + iy * nx + ix;
int nnzrow = 0; int nnzrow = 0;
for (int sz = -1; sz <= 1; sz++) { for (int sz = -1; sz <= 1; sz++) {
for (int sy = -1; sy <= 1; sy++) { for (int sy = -1; sy <= 1; sy++) {
for (int sx = -1; sx <= 1; sx++) { for (int sx = -1; sx <= 1; sx++) {
int curcol = currow + sz * nx * ny + sy * nx + sx; int curcol = currow + sz * nx * ny + sy * nx + sx;
// Since we have a stack of nx by ny by nz domains // Since we have a stack of nx by ny by nz domains
// , stacking in the z direction, we check to see // , stacking in the z direction, we check to see
// if sx and sy are reaching outside of the domain, // if sx and sy are reaching outside of the domain,
// while the check for the curcol being valid is // while the check for the curcol being valid is
// sufficient to check the z values // sufficient to check the z values
if ((ix + sx >= 0) && (ix + sx < nx) && (iy + sy >= 0) && if ((ix + sx >= 0) && (ix + sx < nx) && (iy + sy >= 0) &&
(iy + sy < ny) && (curcol >= 0 && curcol < total_nrow)) { (iy + sy < ny) && (curcol >= 0 && curcol < total_nrow)) {
// This logic will skip over point that are not part of a // This logic will skip over point that are not part of a
// 7-pt stencil // 7-pt stencil
if (!use_7pt_stencil || if (!use_7pt_stencil || (sz * sz + sy * sy + sx * sx <= 1)) {
(sz * sz + sy * sy + sx * sx <= 1)) { if (curcol == currow) {
if (curcol == currow) { *curvalptr++ = 27.0;
*curvalptr++ = 27.0; } else {
} else { *curvalptr++ = -1.0;
*curvalptr++ = -1.0; }
} *curindptr++ = curcol;
*curindptr++ = curcol; nnzrow++;
nnzrow++; }
} }
} } // end sx loop
} // end sx loop } // end sy loop
} // end sy loop } // end sz loop
} // end sz loop
*currowptr = *(currowptr - 1) + nnzrow; *currowptr = *(currowptr - 1) + nnzrow;
currowptr++; currowptr++;
nnzglobal += nnzrow; nnzglobal += nnzrow;
x[curlocalrow] = 0.0; x[curlocalrow] = 0.0;
b[curlocalrow] = 27.0 - ((CG_FLOAT)(nnzrow - 1)); b[curlocalrow] = 27.0 - ((CG_FLOAT)(nnzrow - 1));
xexact[curlocalrow] = 1.0; xexact[curlocalrow] = 1.0;
} // end ix loop } // end ix loop
} // end iy loop } // end iy loop
} // end iz loop } // end iz loop
#ifdef VERBOSE #ifdef VERBOSE
printf("Process %d of %d has %d rows\n", rank, size, local_nrow); printf("Process %d of %d has %d rows\n", rank, size, local_nrow);
printf("Global rows %d through %d\n", start_row, stop_row); printf("Global rows %d through %d\n", start_row, stop_row);
printf("%d nonzeros\n", start_row, stop_row); printf("%d nonzeros\n", start_row, stop_row);
#endif /* ifdef VERBOSE */ #endif /* ifdef VERBOSE */
s->A.startRow = start_row; s->A.startRow = start_row;
s->A.stopRow = stop_row; s->A.stopRow = stop_row;
s->A.totalNr = total_nrow; s->A.totalNr = total_nrow;
s->A.totalNnz = total_nnz; s->A.totalNnz = total_nnz;
s->A.nr = local_nrow; s->A.nr = local_nrow;
s->A.nc = local_nrow; s->A.nc = local_nrow;
s->A.nnz = local_nnz; s->A.nnz = local_nnz;
} }
void initSolver(Solver* s, Comm* c, Parameter* p) void initSolver(Solver* s, Comm* c, Parameter* p)
{ {
if (!strcmp(p->filename, "generate")) { if (!strcmp(p->filename, "generate")) {
matrixGenerate(p, s, c, false); matrixGenerate(p, s, c, false);
} else if (!strcmp(p->filename, "generate7P")) { } else if (!strcmp(p->filename, "generate7P")) {
matrixGenerate(p, s, c, true); matrixGenerate(p, s, c, true);
} else { } else {
matrixRead(&s->A, p->filename); matrixRead(&s->A, p->filename);
} }
} }
void spMVM(Matrix* m, const CG_FLOAT* restrict x, CG_FLOAT* restrict y) void spMVM(Matrix* m, const CG_FLOAT* restrict x, CG_FLOAT* restrict y)
{ {
CG_UINT numRows = m->nr; CG_UINT numRows = m->nr;
CG_UINT* rowPtr = m->rowPtr; CG_UINT* rowPtr = m->rowPtr;
CG_UINT* colInd = m->colInd; CG_UINT* colInd = m->colInd;
CG_FLOAT* val = m->val; CG_FLOAT* val = m->val;
for (size_t rowID = 0; rowID < numRows; rowID++) { for (size_t rowID = 0; rowID < numRows; rowID++) {
CG_FLOAT tmp = y[rowID]; CG_FLOAT tmp = y[rowID];
// loop over all elements in row // loop over all elements in row
for (size_t rowEntry = rowPtr[rowID]; rowEntry < rowPtr[rowID + 1]; rowEntry++) { for (size_t rowEntry = rowPtr[rowID]; rowEntry < rowPtr[rowID + 1];
tmp += val[rowEntry] * x[colInd[rowEntry]]; rowEntry++) {
} tmp += val[rowEntry] * x[colInd[rowEntry]];
y[rowID] = tmp;
} }
y[rowID] = tmp;
}
} }
void waxpby(const CG_UINT n, void waxpby(const CG_UINT n,
@ -155,19 +159,19 @@ void waxpby(const CG_UINT n,
const CG_FLOAT* restrict y, const CG_FLOAT* restrict y,
CG_FLOAT* const w) CG_FLOAT* const w)
{ {
if (alpha == 1.0) { if (alpha == 1.0) {
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
w[i] = x[i] + beta * y[i]; w[i] = x[i] + beta * y[i];
}
} else if (beta == 1.0) {
for (size_t i = 0; i < n; i++) {
w[i] = alpha * x[i] + y[i];
}
} else {
for (size_t i = 0; i < n; i++) {
w[i] = alpha * x[i] + beta * y[i];
}
} }
} else if (beta == 1.0) {
for (size_t i = 0; i < n; i++) {
w[i] = alpha * x[i] + y[i];
}
} else {
for (size_t i = 0; i < n; i++) {
w[i] = alpha * x[i] + beta * y[i];
}
}
} }
void ddot(const CG_UINT n, void ddot(const CG_UINT n,
@ -175,18 +179,18 @@ void ddot(const CG_UINT n,
const CG_FLOAT* restrict y, const CG_FLOAT* restrict y,
CG_FLOAT* restrict result) CG_FLOAT* restrict result)
{ {
CG_FLOAT sum = 0.0; CG_FLOAT sum = 0.0;
if (y == x) { if (y == x) {
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
sum += x[i] * x[i]; sum += x[i] * x[i];
}
} else {
for (size_t i = 0; i < n; i++) {
sum += x[i] * y[i];
}
} }
} else {
for (size_t i = 0; i < n; i++) {
sum += x[i] * y[i];
}
}
commReduction(&sum, SUM); commReduction(&sum, SUM);
*result = sum; *result = sum;
} }

View File

@ -10,10 +10,10 @@
#include "util.h" #include "util.h"
typedef struct { typedef struct {
Matrix A; Matrix A;
CG_FLOAT* x; CG_FLOAT* x;
CG_FLOAT* b; CG_FLOAT* b;
CG_FLOAT* xexact; CG_FLOAT* xexact;
} Solver; } Solver;
void initSolver(Solver* s, Comm* c, Parameter*); void initSolver(Solver* s, Comm* c, Parameter*);

View File

@ -7,14 +7,14 @@
double getTimeStamp(void) double getTimeStamp(void)
{ {
struct timespec ts; struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
return (double)ts.tv_sec + (double)ts.tv_nsec * 1.e-9; return (double)ts.tv_sec + (double)ts.tv_nsec * 1.e-9;
} }
double getTimeResolution(void) double getTimeResolution(void)
{ {
struct timespec ts; struct timespec ts;
clock_getres(CLOCK_MONOTONIC, &ts); clock_getres(CLOCK_MONOTONIC, &ts);
return (double)ts.tv_sec + (double)ts.tv_nsec * 1.e-9; return (double)ts.tv_sec + (double)ts.tv_nsec * 1.e-9;
} }