#include 
#include 
#include 
#include 

// these read-input-from-file functions were made with the help of chatGPT.
void readDoublesFromFile(const char *filePath, double *numbers, size_t numberOfNumbers) {
    FILE *file = fopen(filePath, &#34;r&#34;);
    
    if (file == NULL) {
        printf(&#34;Error opening the file: %s\n&#34;, filePath);
        exit(1);
    }
    
    for (size_t i = 0; i &lt; numberOfNumbers; i++) {
        int result = fscanf(file, &#34;%lf&#34;, &amp;numbers[i]);
        if (result != 1) {
            printf(&#34;Error reading double from file at index %zu, result = %d\n&#34;, i, result);
            fclose(file);
            exit(1);
        }
    }
    
    fclose(file);
}

void readIntsFromFile(const char *filePath, int *numbers, size_t numberOfNumbers) {
    FILE *file = fopen(filePath, &#34;r&#34;);
    
    if (file == NULL) {
        printf(&#34;Error opening the file: %s\n&#34;, filePath);
        exit(1);
    }
    
    for (size_t i = 0; i &lt; numberOfNumbers; i++) {
        int result = fscanf(file, &#34;%d&#34;, &amp;numbers[i]);
        if (result != 1) {
            printf(&#34;Error reading int from file at index %zu, result = %d\n&#34;, i, result);
            fclose(file);
            exit(1);
        }
    }
    
    fclose(file);
}

void readLongsFromFile(const char *filePath, long *numbers, size_t numberOfNumbers) {
    FILE *file = fopen(filePath, &#34;r&#34;);
    
    if (file == NULL) {
        printf(&#34;Error opening the file: %s\n&#34;, filePath);
        exit(1);
    }

    for (size_t i = 0; i &lt; numberOfNumbers; i++) {
        int result = fscanf(file, &#34;%ld&#34;, &amp;numbers[i]);
        if (result != 1) {
            printf(&#34;Error reading long from file at index %zu, result = %d\n&#34;, i, result);
            fclose(file);
            exit(1);
        }
    }
    
    fclose(file);
}

int main() {
    const char *rowvalPath = &#34;pglib_opf_case30000_rowval.txt&#34;;
    const char *colptrPath = &#34;pglib_opf_case30000_colptr.txt&#34;;
    const char *nzvalPath = &#34;pglib_opf_case30000_nzval.txt&#34;;
    size_t numberOfNumbers = 65231;
    size_t colptrLen = 30000;
    size_t N = colptrLen - 1;

    int *rowval = (int *)malloc(numberOfNumbers * sizeof(int));
    long *colptr = (long *)malloc(colptrLen * sizeof(long));
    double *nzval = (double *)malloc(numberOfNumbers * sizeof(double));
    
    if (rowval == NULL || colptr == NULL || nzval == NULL) {
        printf(&#34;Memory allocation failed.\n&#34;);
        return 1;
    }

    readIntsFromFile(rowvalPath, rowval, numberOfNumbers);
    readLongsFromFile(colptrPath, colptr, colptrLen);
    readDoublesFromFile(nzvalPath, nzval, numberOfNumbers);

    SparseMatrixStructure s = {
        .rowCount     = N,
        .columnCount  = N,
        .columnStarts = colptr,
        .rowIndices   = rowval,
        .attributes = {
            .triangle = SparseLowerTriangle,
            .kind = SparseSymmetric,
        },
        .blockSize = 1,
    };

    SparseMatrix_Double ABA = {
        .structure = s,
        .data = nzval
    };
    
    clock_t start1, end1;
    start1 = clock();
    SparseOpaqueFactorization_Double f = SparseFactor(SparseFactorizationCholesky, ABA);
    end1 = clock();
    printf(&#34;time for factoring: %lf\n&#34;, ((double) (end1 - start1)) / CLOCKS_PER_SEC);

    size_t M = 10000;
    double* randomVs = (double *)malloc(M*N * sizeof(double));
    if (randomVs == NULL){
        printf(&#34;allocation failed&#34;);
        return 1;
    }

    srand(time(NULL));
    for (int i = 0; i &lt; M*N; ++i)
        randomVs[i] = ((double) rand())/RAND_MAX;

    clock_t start2, end2;
    start2 = clock();
    for (int i = 0; i &lt; M*N; i += N){
        DenseVector_Double b = {
            .count = N,
            .data = randomVs + i
        };
        SparseSolve(f, b);
    }
    end2 = clock();
    printf(&#34;time for 10k in-place solves: %lf\n&#34;, ((double) (end2 - start2)) / CLOCKS_PER_SEC);
    // Free the allocated memory
    free(rowval);
    free(colptr);
    free(nzval);
    SparseCleanup(f);
    free(randomVs);
    return 0;
}
