blob: 80fb6f4766b80f736ef57a265848aff703185b87 [file] [log] [blame]
/************************************************************************************\
* *
* Copyright � 2014 Advanced Micro Devices, Inc. *
* Copyright (c) 2015 Mark D. Hill and David A. Wood *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following are met: *
* *
* You must reproduce the above copyright notice. *
* *
* Neither the name of the copyright holder nor the names of its contributors *
* may be used to endorse or promote products derived from this software *
* without specific, prior, written permission from at least the copyright holder. *
* *
* You must include the following terms in your license and/or other materials *
* provided with the software. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" *
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *
* IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN *
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING *
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY *
* OF SUCH DAMAGE. *
* *
* Without limiting the foregoing, the software may implement third party *
* technologies for which you must obtain licenses from parties other than AMD. *
* You agree that AMD has not obtained or conveyed to you, and that you shall *
* be responsible for obtaining the rights to use and/or distribute the applicable *
* underlying intellectual property rights related to the third party technologies. *
* These third party technologies are not licensed hereunder. *
* *
* If you use the software (in whole or in part), you shall adhere to all *
* applicable U.S., European, and other export laws, including but not limited to *
* the U.S. Export Administration Regulations ("EAR") (15 C.F.R Sections 730-774), *
* and E.U. Council Regulation (EC) No 428/2009 of 5 May 2009. Further, pursuant *
* to Section 740.6 of the EAR, you hereby certify that, except pursuant to a *
* license granted by the United States Department of Commerce Bureau of Industry *
* and Security or as otherwise permitted pursuant to a License Exception under *
* the U.S. Export Administration Regulations ("EAR"), you will not (1) export, *
* re-export or release to a national of a country in Country Groups D:1, E:1 or *
* E:2 any restricted technology, software, or source code you receive hereunder, *
* or (2) export to Country Groups D:1, E:1 or E:2 the direct product of such *
* technology or software, if such foreign produced direct product is subject to *
* national security controls as identified on the Commerce Control List (currently *
* found in Supplement 1 to Part 774 of EAR). For the most current Country Group *
* listings, or for additional information about the EAR or your obligations under *
* those regulations, please refer to the U.S. Bureau of Industry and Security's *
* website at http://www.bis.doc.gov/. *
* *
\************************************************************************************/
#include "parse.h"
#include "stdlib.h"
#include "stdio.h"
#include <string.h>
#include <algorithm>
#include <sys/time.h>
#include "util.h"
bool doCompare(CooTuple elem1, CooTuple elem2)
{
if (elem1.row < elem2.row) {
return true;
}
return false;
}
ell_array *csr2ell(csr_array *csr, int num_nodes, int num_edges, int fill)
{
int size, maxheight = 0;
for (int i = 0; i < num_nodes; i++) {
size = csr->row_array[i + 1] - csr->row_array[i];
if (size > maxheight)
maxheight = size;
}
ell_array *ell = (ell_array *)malloc(sizeof(ell_array));
if (!ell) printf("malloc failed");
ell->max_height = maxheight;
ell->num_nodes = num_nodes;
ell->col_array = (int*)malloc(sizeof(int) * maxheight * num_nodes);
ell->data_array = (int*)malloc(sizeof(int) * maxheight * num_nodes);
for (int i = 0; i < maxheight * num_nodes; i++) {
ell->col_array[i] = 0;
ell->data_array[i] = fill;
}
for (int i = 0; i < num_nodes; i++) {
int start = csr->row_array[i];
int end = csr->row_array[i + 1];
int lastcolid = 0;
for (int j = start; j < end; j++) {
int colid = csr->col_array[j];
int data = csr->data_array[j];
ell->col_array[i + (j - start) * num_nodes] = colid;
ell->data_array[i + (j - start) * num_nodes] = data;
lastcolid = colid;
}
for (int j = end; j < start + maxheight; j++) {
ell->col_array[i + (j - start) * num_nodes] = lastcolid;
ell->data_array[i + (j - start) * num_nodes] = fill;
}
}
return ell;
}
csr_array *parseMetis(char* tmpchar, int *p_num_nodes, int *p_num_edges, bool directed)
{
int cnt = 0;
unsigned int lineno = 0;
char *line = (char *)malloc(8192);
int num_edges = 0, num_nodes = 0;
FILE *fptr;
CooTuple *tuple_array = NULL;
fptr = fopen(tmpchar, "r");
if (!fptr) {
fprintf(stderr, "Error when opening file: %s\n", tmpchar);
exit(1);
}
printf("Opening file: %s\n", tmpchar);
while (fgets(line, 8192, fptr)) {
int head, tail, weight = 0;
CooTuple temp;
if (line[0] == '%') continue; // skip comment lines
if (lineno == 0) { //the first line
sscanf(line, "%d %d", p_num_nodes, p_num_edges);
if (!directed) {
*p_num_edges = *p_num_edges * 2;
printf("This is an undirected graph\n");
} else {
printf("This is a directed graph\n");
}
num_nodes = *p_num_nodes;
num_edges = *p_num_edges;
printf("Read from file: num_nodes = %d, num_edges = %d\n", num_nodes, num_edges);
tuple_array = (CooTuple *)malloc(sizeof(CooTuple) * num_edges);
} else if (lineno > 0) { //from the second line
char *pch;
pch = strtok(line , " ,.-");
while (pch != NULL) {
head = lineno;
tail = atoi(pch);
if (tail <= 0) break;
if (tail == head) printf("reporting self loop: %d, %d\n", lineno + 1, lineno);
temp.row = head - 1;
temp.col = tail - 1;
temp.val = weight;
tuple_array[cnt++] = temp;
pch = strtok(NULL, " ,.-");
}
}
#ifdef VERBOSE
printf("Adding edge: %d ==> %d ( %d )\n", head, tail, weight);
#endif
lineno++;
}
// Metis files are stored in row-order, so sorting is unnecessary
// std::stable_sort(tuple_array, tuple_array + num_edges, doCompare);
#ifdef VERBOSE
for (int i = 0 ; i < num_edges; i++) {
printf("%d: %d, %d, %d\n", i, tuple_array[i].row, tuple_array[i].col, tuple_array[i].val);
}
#endif
int *row_array = (int *)malloc((num_nodes + 1) * sizeof(int));
int *col_array = (int *)malloc(num_edges * sizeof(int));
int *data_array = (int *)malloc(num_edges * sizeof(int));
int row_cnt = 0;
int prev = -1;
int idx;
for (idx = 0; idx < num_edges; idx++) {
int curr = tuple_array[idx].row;
if (curr != prev) {
row_array[row_cnt++] = idx;
prev = curr;
}
col_array[idx] = tuple_array[idx].col;
data_array[idx] = tuple_array[idx].val;
}
row_array[row_cnt] = idx;
csr_array *csr = (csr_array *)malloc(sizeof(csr_array));
memset(csr, 0, sizeof(csr_array));
csr->row_array = row_array;
csr->col_array = col_array;
csr->data_array = data_array;
fclose(fptr);
free(tuple_array);
free(line);
return csr;
}
csr_array *parseCOO(char* tmpchar, int *p_num_nodes, int *p_num_edges, bool directed)
{
int cnt = 0;
unsigned int lineno = 0;
char line[128], sp[2], a, p;
int num_nodes = 0, num_edges = 0;
FILE *fptr;
CooTuple *tuple_array = NULL;
fptr = fopen(tmpchar, "r");
if (!fptr) {
fprintf(stderr, "Error when opening file: %s\n", tmpchar);
exit(1);
}
printf("Opening file: %s\n", tmpchar);
while (fgets(line, 100, fptr)) {
int head, tail, weight;
switch (line[0]) {
case 'c':
break;
case 'p':
sscanf(line, "%c %s %d %d", &p, sp, p_num_nodes, p_num_edges);
if (!directed) {
*p_num_edges = *p_num_edges * 2;
printf("This is an undirected graph\n");
} else {
printf("This is a directed graph\n");
}
num_nodes = *p_num_nodes;
num_edges = *p_num_edges;
printf("Read from file: num_nodes = %d, num_edges = %d\n", num_nodes, num_edges);
tuple_array = (CooTuple *)malloc(sizeof(CooTuple) * num_edges);
break;
case 'a':
sscanf(line, "%c %d %d %d", &a, &head, &tail, &weight);
if (tail == head) printf("reporting self loop\n");
CooTuple temp;
temp.row = head - 1;
temp.col = tail - 1;
temp.val = weight;
tuple_array[cnt++] = temp;
if (!directed) {
temp.row = tail - 1;
temp.col = head - 1;
temp.val = weight;
tuple_array[cnt++] = temp;
}
#ifdef VERBOSE
printf("Adding edge: %d ==> %d ( %d )\n", head, tail, weight);
#endif
break;
default:
fprintf(stderr, "exiting loop\n");
break;
}
lineno++;
}
std::stable_sort(tuple_array, tuple_array + num_edges, doCompare);
#ifdef VERBOSE
for (int i = 0 ; i < num_edges; i++) {
printf("%d: %d, %d, %d\n", i, tuple_array[i].row, tuple_array[i].col, tuple_array[i].val);
}
#endif
int *row_array = (int *)malloc((num_nodes + 1) * sizeof(int));
int *col_array = (int *)malloc(num_edges * sizeof(int));
int *data_array = (int *)malloc(num_edges * sizeof(int));
int row_cnt = 0;
int prev = -1;
int idx;
for (idx = 0; idx < num_edges; idx++) {
int curr = tuple_array[idx].row;
if (curr != prev) {
row_array[row_cnt++] = idx;
prev = curr;
}
col_array[idx] = tuple_array[idx].col;
data_array[idx] = tuple_array[idx].val;
}
row_array[row_cnt] = idx;
fclose(fptr);
free(tuple_array);
csr_array *csr = (csr_array *)malloc(sizeof(csr_array));
memset(csr, 0, sizeof(csr_array));
csr->row_array = row_array;
csr->col_array = col_array;
csr->data_array = data_array;
return csr;
}
// Parse Metis file with double edges
double_edges *parseMetis_doubleEdge(char* tmpchar, int *p_num_nodes, int *p_num_edges, bool directed)
{
int cnt = 0;
unsigned int lineno = 0;
char line[4096];
int num_edges = 0, num_nodes = 0;
FILE *fptr;
CooTuple *tuple_array = NULL;
fptr = fopen(tmpchar, "r");
if (!fptr) {
fprintf(stderr, "Error when opening file: %s\n", tmpchar);
exit(1);
}
printf("Opening file: %s\n", tmpchar);
while (fgets(line, 4096, fptr)) {
int head, tail, weight = 0;
CooTuple temp;
if (line[0] == '%') continue; // skip comment lines
if (lineno == 0) { //the first line
sscanf(line, "%d %d", p_num_nodes, p_num_edges);
if (!directed) {
*p_num_edges = *p_num_edges * 2;
printf("This is an undirected graph\n");
} else {
printf("This is a directed graph\n");
}
num_nodes = *p_num_nodes;
num_edges = *p_num_edges;
printf("Read from file: num_nodes = %d, num_edges = %d\n", num_nodes, num_edges);
tuple_array = (CooTuple *)malloc(sizeof(CooTuple) * num_edges);
if (!tuple_array) printf("xxxxxxxx\n");
} else if (lineno > 0) { //from the second line
char *pch;
pch = strtok(line , " ,.-");
while (pch != NULL) {
head = lineno;
tail = atoi(pch);
if (tail <= 0) break;
if (tail == head) printf("reporting self loop: %d, %d\n", lineno + 1, lineno);
temp.row = head - 1;
temp.col = tail - 1;
temp.val = weight;
tuple_array[cnt++] = temp;
pch = strtok(NULL, " ,.-");
}
}
#ifdef VERBOSE
printf("Adding edge: %d ==> %d ( %d )\n", head, tail, weight);
#endif
lineno++;
}
// Metis files are stored in row-order, so sorting is unnecessary
// std::stable_sort(tuple_array, tuple_array + num_edges, doCompare);
#ifdef VERBOSE
for (int i = 0 ; i < num_edges; i++) {
printf("%d: %d, %d, %d\n", i, tuple_array[i].row, tuple_array[i].col, tuple_array[i].val);
}
#endif
int *edge_array1 = (int *)malloc(num_edges * sizeof(int));
int *edge_array2 = (int *)malloc(num_edges * sizeof(int));
for (int i = 0; i < num_edges; i++) {
edge_array1[i] = tuple_array[i].row;
edge_array2[i] = tuple_array[i].col;
}
fclose(fptr);
free(tuple_array);
double_edges *de = (double_edges *)malloc(sizeof(double_edges));
de->edge_array1 = edge_array1;
de->edge_array2 = edge_array2;
return de;
}
// Parse COO file with double edges
double_edges *parseCOO_doubleEdge(char* tmpchar, int *p_num_nodes, int *p_num_edges, bool directed)
{
int cnt = 0;
unsigned int lineno = 0;
char line[128], sp[2], a, p;
int num_nodes = 0, num_edges = 0;
FILE *fptr;
CooTuple *tuple_array = NULL;
fptr = fopen(tmpchar, "r");
if (!fptr) {
fprintf(stderr, "Error when opening file: %s\n", tmpchar);
exit(1);
}
printf("Opening file: %s\n", tmpchar);
while (fgets(line, 100, fptr)) {
int head, tail, weight;
switch (line[0]) {
case 'c':
break;
case 'p':
sscanf(line, "%c %s %d %d", &p, sp, p_num_nodes, p_num_edges);
if (!directed) {
*p_num_edges = *p_num_edges * 2;
printf("This is an undirected graph\n");
} else {
printf("This is a directed graph\n");
}
num_nodes = *p_num_nodes;
num_edges = *p_num_edges;
printf("Read from file: num_nodes = %d, num_edges = %d\n", num_nodes, num_edges);
tuple_array = (CooTuple *)malloc(sizeof(CooTuple) * num_edges);
break;
case 'a':
sscanf(line, "%c %d %d %d", &a, &head, &tail, &weight);
if (tail == head) printf("reporting self loop\n");
CooTuple temp;
temp.row = head - 1;
temp.col = tail - 1;
temp.val = weight;
tuple_array[cnt++] = temp;
if (!directed) {
temp.row = tail - 1;
temp.col = head - 1;
temp.val = weight;
tuple_array[cnt++] = temp;
}
#ifdef VERBOSE
printf("Adding edge: %d ==> %d ( %d )\n", head, tail, weight);
#endif
break;
default:
fprintf(stderr, "exiting loop\n");
break;
}
lineno++;
}
std::stable_sort(tuple_array, tuple_array + num_edges, doCompare);
#ifdef VERBOSE
for (int i = 0 ; i < num_edges; i++) {
printf("%d: %d, %d, %d\n", i, tuple_array[i].row, tuple_array[i].col, tuple_array[i].val);
}
#endif
int *edge_array1 = (int *)malloc(num_edges * sizeof(int));
int *edge_array2 = (int *)malloc(num_edges * sizeof(int));
for (int i = 0; i < num_edges; i++) {
edge_array1[i] = tuple_array[i].row;
edge_array2[i] = tuple_array[i].col;
}
fclose(fptr);
free(tuple_array);
double_edges *de = (double_edges *)malloc(sizeof(double_edges));
de->edge_array1 = edge_array1;
de->edge_array2 = edge_array2;
return de;
}
// Parse matrix market file
csr_array *parseMM(char* tmpchar, int *p_num_nodes, int *p_num_edges, bool directed, bool weight_flag)
{
int cnt = 0;
unsigned int lineno = 0;
char line[128];
int num_nodes = 0, num_edges = 0, num_nodes2 = 0;
FILE *fptr;
CooTuple *tuple_array = NULL;
fptr = fopen(tmpchar, "r");
if (!fptr) {
fprintf(stderr, "Error when opening file: %s\n", tmpchar);
exit(1);
}
printf("Opening file: %s\n", tmpchar);
while (fgets(line, 100, fptr)) {
int head, tail, weight;
if (line[0] == '%') continue;
if (lineno == 0) {
sscanf(line, "%d %d %d", p_num_nodes, &num_nodes2, p_num_edges);
if (!directed) {
*p_num_edges = *p_num_edges * 2;
printf("This is an undirected graph\n");
} else {
printf("This is a directed graph\n");
}
num_nodes = *p_num_nodes;
num_edges = *p_num_edges;
printf("Read from file: num_nodes = %d, num_edges = %d\n", num_nodes, num_edges);
tuple_array = (CooTuple *)malloc(sizeof(CooTuple) * num_edges);
if (!tuple_array) {
printf("tuple array not allocated succesfully\n");
exit(1);
}
}
if (lineno > 0) {
if (weight_flag) {
sscanf(line, "%d %d %d", &head, &tail, &weight);
} else {
sscanf(line, "%d %d", &head, &tail);
printf("(%d, %d)\n", head, tail);
weight = 0;
}
if (tail == head) {
printf("reporting self loop\n");
continue;
};
CooTuple temp;
temp.row = head - 1;
temp.col = tail - 1;
temp.val = weight;
tuple_array[cnt++] = temp;
if (!directed) {
temp.row = tail - 1;
temp.col = head - 1;
temp.val = weight;
tuple_array[cnt++] = temp;
}
#ifdef VERBOSE
printf("Adding edge: %d ==> %d ( %d )\n", head, tail, weight);
#endif
}
lineno++;
}
std::stable_sort(tuple_array, tuple_array + num_edges, doCompare);
#ifdef VERBOSE
for (int i = 0 ; i < num_edges; i++) {
printf("%d: %d, %d, %d\n", i, tuple_array[i].row, tuple_array[i].col, tuple_array[i].val);
}
#endif
int *row_array = (int *)malloc((num_nodes + 1) * sizeof(int));
int *col_array = (int *)malloc(num_edges * sizeof(int));
int *data_array = (int *)malloc(num_edges * sizeof(int));
int row_cnt = 0;
int prev = -1;
int idx;
for (idx = 0; idx < num_edges; idx++) {
int curr = tuple_array[idx].row;
if (curr != prev) {
row_array[row_cnt++] = idx;
prev = curr;
}
col_array[idx] = tuple_array[idx].col;
data_array[idx] = tuple_array[idx].val;
}
row_array[row_cnt] = idx;
fclose(fptr);
free(tuple_array);
csr_array *csr = (csr_array *)malloc(sizeof(csr_array));
memset(csr, 0, sizeof(csr_array));
csr->row_array = row_array;
csr->col_array = col_array;
csr->data_array = data_array;
return csr;
}
// Parse Metis file with transpose
csr_array *parseMetis_transpose(char* tmpchar, int *p_num_nodes, int *p_num_edges, bool directed)
{
int cnt = 0;
unsigned int lineno = 0;
char *line = (char *)malloc(8192);
int num_edges = 0, num_nodes = 0;
int *col_cnt = NULL;
FILE *fptr;
CooTuple *tuple_array = NULL;
fptr = fopen(tmpchar, "r");
if (!fptr) {
fprintf(stderr, "Error when opening file: %s\n", tmpchar);
exit(1);
}
printf("Opening file: %s\n", tmpchar);
while (fgets(line, 8192, fptr)) {
int head, tail, weight = 0;
CooTuple temp;
if (line[0] == '%') continue; // skip comment lines
if (lineno == 0) { //the first line
sscanf(line, "%d %d", p_num_nodes, p_num_edges);
col_cnt = (int *)malloc(*p_num_nodes * sizeof(int));
if (!col_cnt) {
printf("memory allocation failed for col_cnt\n");
exit(1);
}
memset(col_cnt, 0, *p_num_nodes * sizeof(int));
if (!directed) {
*p_num_edges = *p_num_edges * 2;
printf("This is an undirected graph\n");
} else {
printf("This is a directed graph\n");
}
num_nodes = *p_num_nodes;
num_edges = *p_num_edges;
printf("Read from file: num_nodes = %d, num_edges = %d\n", num_nodes, num_edges);
tuple_array = (CooTuple *)malloc(sizeof(CooTuple) * num_edges);
} else if (lineno > 0) { //from the second line
char *pch;
pch = strtok(line , " ,.-");
while (pch != NULL) {
head = lineno;
tail = atoi(pch);
if (tail <= 0) {
break;
}
if (tail == head) printf("reporting self loop: %d, %d\n", lineno + 1, lineno);
if (directed) {
temp.row = tail - 1;
temp.col = head - 1;
} else {
// Undirected matrices are symmetric, so there is no need
// to transpose and then re-sort the edges
temp.row = head - 1;
temp.col = tail - 1;
}
temp.val = weight;
col_cnt[head - 1]++;
if (cnt >= num_edges) {
fprintf(stderr, "Error when opening file: %s.\n" \
" Check if graph is undirected Metis format\n", tmpchar);
exit(1);
}
tuple_array[cnt++] = temp;
pch = strtok(NULL, " ,.-");
}
}
#ifdef VERBOSE
printf("Adding edge: %d ==> %d ( %d )\n", head, tail, weight);
#endif
lineno++;
}
if (directed) {
// Metis files are stored in row-order, so transposed, directed
// matrices must be re-sorted!
std::stable_sort(tuple_array, tuple_array + num_edges, doCompare);
}
#ifdef VERBOSE
for (int i = 0 ; i < num_edges; i++) {
printf("%d: %d, %d, %d\n", i, tuple_array[i].row, tuple_array[i].col, tuple_array[i].val);
}
#endif
int *row_array = (int *)malloc((num_nodes + 1) * sizeof(int));
int *col_array = (int *)malloc(num_edges * sizeof(int));
int *data_array = (int *)malloc(num_edges * sizeof(int));
int row_cnt = 0;
int prev = -1;
int idx;
for (idx = 0; idx < num_edges; idx++) {
int curr = tuple_array[idx].row;
if (curr != prev) {
row_array[row_cnt++] = idx;
prev = curr;
}
col_array[idx] = tuple_array[idx].col;
data_array[idx] = tuple_array[idx].val;
}
row_array[row_cnt] = idx;
csr_array *csr = (csr_array *)malloc(sizeof(csr_array));
memset(csr, 0, sizeof(csr_array));
csr->row_array = row_array;
csr->col_array = col_array;
csr->data_array = data_array;
csr->col_cnt = col_cnt;
fclose(fptr);
free(tuple_array);
return csr;
}
// Parse COO file with transpose
csr_array *parseCOO_transpose(char* tmpchar, int *p_num_nodes, int *p_num_edges, bool directed)
{
int cnt = 0;
unsigned int lineno = 0;
char line[128], sp[2], a, p;
int num_nodes = 0, num_edges = 0;
FILE *fptr;
CooTuple *tuple_array = NULL;
fptr = fopen(tmpchar, "r");
if (!fptr) {
fprintf(stderr, "Error when opening file: %s\n", tmpchar);
exit(1);
}
printf("Opening file: %s\n", tmpchar);
while (fgets(line, 100, fptr)) {
int head, tail, weight;
switch (line[0]) {
case 'c':
break;
case 'p':
fflush(stdout);
sscanf(line, "%c %s %d %d", &p, sp, p_num_nodes, p_num_edges);
if (!directed) {
*p_num_edges = *p_num_edges * 2;
printf("This is an undirected graph\n");
} else {
printf("This is a directed graph\n");
}
num_nodes = *p_num_nodes;
num_edges = *p_num_edges;
printf("Read from file: num_nodes = %d, num_edges = %d\n", num_nodes, num_edges);
tuple_array = (CooTuple *)malloc(sizeof(CooTuple) * num_edges);
break;
case 'a':
sscanf(line, "%c %d %d %d", &a, &head, &tail, &weight);
if (tail == head) printf("reporting self loop\n");
CooTuple temp;
temp.val = weight;
temp.row = tail - 1;
temp.col = head - 1;
tuple_array[cnt++] = temp;
if (!directed) {
temp.val = weight;
temp.row = tail - 1;
temp.col = head - 1;
tuple_array[cnt++] = temp;
}
#ifdef VERBOSE
printf("Adding edge: %d ==> %d ( %d )\n", head, tail, weight);
#endif
break;
default:
fprintf(stderr, "exiting loop\n");
break;
}
lineno++;
}
std::stable_sort(tuple_array, tuple_array + num_edges, doCompare);
#ifdef VERBOSE
for (int i = 0 ; i < num_edges; i++) {
printf("%d: %d, %d, %d\n", i, tuple_array[i].row, tuple_array[i].col, tuple_array[i].val);
}
#endif
int *row_array = (int *)malloc((num_nodes + 1) * sizeof(int));
int *col_array = (int *)malloc(num_edges * sizeof(int));
int *data_array = (int *)malloc(num_edges * sizeof(int));
int row_cnt = 0;
int prev = -1;
int idx;
for (idx = 0; idx < num_edges; idx++) {
int curr = tuple_array[idx].row;
if (curr != prev) {
row_array[row_cnt++] = idx;
prev = curr;
}
col_array[idx] = tuple_array[idx].col;
data_array[idx] = tuple_array[idx].val;
}
while (row_cnt <= num_nodes) {
row_array[row_cnt++] = idx;
}
csr_array *csr = (csr_array *)malloc(sizeof(csr_array));
memset(csr, 0, sizeof(csr_array));
csr->row_array = row_array;
csr->col_array = col_array;
csr->data_array = data_array;
fclose(fptr);
free(tuple_array);
return csr;
}