Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44e68aa0a9 | ||
|
|
4b3127d84d | ||
|
|
fa1af3ade8 | ||
|
|
b2d4f7dac4 | ||
|
|
85f5fc43d7 | ||
|
|
4d35b7d8de | ||
|
|
43eb0ab212 | ||
|
|
8347422cf7 | ||
|
|
262657e0f9 | ||
|
|
a4907f39ff | ||
|
|
80f263a03b | ||
|
|
61da1c14c9 | ||
|
|
394f16e41a | ||
|
|
e31b882445 | ||
|
|
2bf94bb57f | ||
|
|
251523a949 | ||
|
|
ad674c03ba |
+2
-5
@@ -1,6 +1,3 @@
|
|||||||
.swp
|
.swp
|
||||||
test
|
.vscode
|
||||||
test2
|
*.txt
|
||||||
test_loader
|
|
||||||
time
|
|
||||||
.vscode
|
|
||||||
@@ -1,2 +1,4 @@
|
|||||||
# Lina
|
# Lina, the nice-to-read linear algebra toolkit!
|
||||||
Lina (***Lin**ear **A**lgebra*) is a C library that implements common linear algebra operations.
|
Lina (***Lin**ear **A**lgebra*) is a C library that implements common linear algebra operations with the aim to be nice to read!
|
||||||
|
|
||||||
|
The performance branch focuses only on the core functionalities of lina and aims to produce faster and reliable routines.
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
#include <time.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "../src/lina.h"
|
||||||
|
|
||||||
|
#define A_ROWS 960llu
|
||||||
|
#define A_COLS 960llu
|
||||||
|
|
||||||
|
#define B_ROWS 960llu
|
||||||
|
#define B_COLS 960llu
|
||||||
|
|
||||||
|
int saveMatrixToStream(FILE *fp, double *A, int width, int height, char **error);
|
||||||
|
static uint64_t nanos();
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
uint64_t ops = A_ROWS*B_COLS*2*A_COLS;
|
||||||
|
uint64_t start,stop,lina_dot_time, lina_dot1_time, lina_dot2_time, lina_dot3_time, lina_dot4_time;
|
||||||
|
|
||||||
|
double *A = (double *)aligned_alloc(32,sizeof(double)*A_ROWS*A_COLS);
|
||||||
|
double *B = (double *)aligned_alloc(32,sizeof(double)*B_ROWS*B_COLS);
|
||||||
|
|
||||||
|
double *C1 = (double *)aligned_alloc(32,sizeof(double)*A_ROWS*B_COLS);
|
||||||
|
double *C2 = (double *)aligned_alloc(32,sizeof(double)*A_ROWS*B_COLS);
|
||||||
|
double *C3 = (double *)aligned_alloc(32,sizeof(double)*A_ROWS*B_COLS);
|
||||||
|
double *C4 = (double *)aligned_alloc(32,sizeof(double)*A_ROWS*B_COLS);
|
||||||
|
double *C5 = (double *)aligned_alloc(32,sizeof(double)*A_ROWS*B_COLS);
|
||||||
|
|
||||||
|
for (int i = 0; i < A_ROWS*A_COLS; i++)
|
||||||
|
A[i] = (double)(rand()%2);
|
||||||
|
for (int i = 0; i < B_ROWS*B_COLS; i++)
|
||||||
|
B[i] = (double)(rand()%2);
|
||||||
|
for (int i = 0; i < A_ROWS*B_COLS; i++)
|
||||||
|
{
|
||||||
|
C1[i] = (double)(rand()%2);
|
||||||
|
C2[i] = (double)(rand()%2);
|
||||||
|
C3[i] = (double)(rand()%2);
|
||||||
|
C4[i] = (double)(rand()%2);
|
||||||
|
C5[i] = (double)(rand()%2);
|
||||||
|
}
|
||||||
|
|
||||||
|
start = nanos();
|
||||||
|
lina_dot(A,B,C1,A_ROWS,A_COLS,B_COLS);
|
||||||
|
stop = nanos();
|
||||||
|
|
||||||
|
lina_dot_time = stop-start;
|
||||||
|
|
||||||
|
start = nanos();
|
||||||
|
lina_dot1(A,B,C2,A_ROWS,A_COLS,B_COLS);
|
||||||
|
stop = nanos();
|
||||||
|
|
||||||
|
lina_dot1_time = stop-start;
|
||||||
|
|
||||||
|
start = nanos();
|
||||||
|
lina_dot2(A,B,C3,A_ROWS,A_COLS,B_COLS);
|
||||||
|
stop = nanos();
|
||||||
|
|
||||||
|
lina_dot2_time = stop-start;
|
||||||
|
|
||||||
|
start = nanos();
|
||||||
|
lina_dot3(A,B,C4,A_ROWS,A_COLS,B_COLS);
|
||||||
|
stop = nanos();
|
||||||
|
|
||||||
|
lina_dot3_time = stop-start;
|
||||||
|
|
||||||
|
start = nanos();
|
||||||
|
lina_dot4(A,B,C5,A_ROWS,A_COLS,B_COLS);
|
||||||
|
stop = nanos();
|
||||||
|
|
||||||
|
lina_dot4_time = stop-start;
|
||||||
|
|
||||||
|
if(!memcmp(C1,C2,sizeof(double)*A_ROWS*B_COLS)
|
||||||
|
&& !memcmp(C2,C3,sizeof(double)*A_ROWS*B_COLS)
|
||||||
|
&& !memcmp(C3,C4,sizeof(double)*A_ROWS*B_COLS)
|
||||||
|
&& !memcmp(C4,C5,sizeof(double)*A_ROWS*B_COLS))
|
||||||
|
{
|
||||||
|
printf( "lina_dot : %f GFLOPS\n"
|
||||||
|
"lina_dot1: %f GFLOPS\n"
|
||||||
|
"lina_dot2: %f GFLOPS\n"
|
||||||
|
"lina_dot3: %f GFLOPS\n"
|
||||||
|
"lina_dot4: %f GFLOPS\n", (double)ops/lina_dot_time,
|
||||||
|
(double)ops/lina_dot1_time,
|
||||||
|
(double)ops/lina_dot2_time,
|
||||||
|
(double)ops/lina_dot3_time,
|
||||||
|
(double)ops/lina_dot4_time);
|
||||||
|
FILE *fp = fopen("lina_dots_success.txt", "w");
|
||||||
|
if (!fp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
saveMatrixToStream(fp,C1,A_ROWS,A_COLS,NULL);
|
||||||
|
fprintf(fp,"\nFINE\n");
|
||||||
|
saveMatrixToStream(fp,C2,A_ROWS,A_COLS,NULL);
|
||||||
|
fprintf(fp,"\nFINE\n");
|
||||||
|
saveMatrixToStream(fp,C3,A_ROWS,A_COLS,NULL);
|
||||||
|
fprintf(fp,"\nFINE\n");
|
||||||
|
saveMatrixToStream(fp,C4,A_ROWS,A_COLS,NULL);
|
||||||
|
fprintf(fp,"\nFINE\n");
|
||||||
|
saveMatrixToStream(fp,C5,A_ROWS,A_COLS,NULL);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("ERRORE: i prodotti matriciali sono diversi!\n");
|
||||||
|
FILE *fp = fopen("lina_dots_error.txt", "w");
|
||||||
|
if (!fp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
saveMatrixToStream(fp,C1,A_ROWS,A_COLS,NULL);
|
||||||
|
fprintf(fp,"\nFINE\n");
|
||||||
|
saveMatrixToStream(fp,C2,A_ROWS,A_COLS,NULL);
|
||||||
|
fprintf(fp,"\nFINE\n");
|
||||||
|
saveMatrixToStream(fp,C3,A_ROWS,A_COLS,NULL);
|
||||||
|
fprintf(fp,"\nFINE\n");
|
||||||
|
saveMatrixToStream(fp,C4,A_ROWS,A_COLS,NULL);
|
||||||
|
fprintf(fp,"\nFINE\n");
|
||||||
|
saveMatrixToStream(fp,C5,A_ROWS,A_COLS,NULL);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(A);
|
||||||
|
free(B);
|
||||||
|
free(C1);
|
||||||
|
free(C2);
|
||||||
|
free(C3);
|
||||||
|
free(C4);
|
||||||
|
free(C5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t nanos()
|
||||||
|
{
|
||||||
|
struct timespec time;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||||
|
return (uint64_t)time.tv_sec*1000000000 + (uint64_t)time.tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
int saveMatrixToStream(FILE *fp, double *A, int width, int height, char **error)
|
||||||
|
{
|
||||||
|
assert(A != NULL);
|
||||||
|
|
||||||
|
char *dummy;
|
||||||
|
if (error == NULL)
|
||||||
|
error = &dummy;
|
||||||
|
else
|
||||||
|
*error = NULL;
|
||||||
|
|
||||||
|
if (width < 1) {
|
||||||
|
*error = "The provided width is less than one";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height < 1) {
|
||||||
|
*error = "The provided height is less than one";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
fp = stdout;
|
||||||
|
|
||||||
|
putc('[',fp);
|
||||||
|
|
||||||
|
for (int i = 0; i < height-1; i++) {
|
||||||
|
for (int j = 0; j < width-1; j++)
|
||||||
|
fprintf(fp, "%.1f ", A[i*width + j]);
|
||||||
|
|
||||||
|
fprintf(fp, "%.1f,\n", A[i*width + width-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < width-1; j++)
|
||||||
|
fprintf(fp, "%.1f ", A[(height-1)*width + j]);
|
||||||
|
|
||||||
|
fprintf(fp, "%.1f", A[(height-1)*width + width-1]);
|
||||||
|
|
||||||
|
putc(']',fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
gcc bench_dot.c ../src/lina.c -O3 -march=native -ffast-math -funroll-loops -o bench_dot
|
||||||
|
./bench_dot
|
||||||
|
python3 py_dot.py
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import os
|
||||||
|
os.environ['OMP_NUM_THREADS'] = '1'
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
|
||||||
|
N = 1024
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
A = np.random.randn(N,N).astype(np.float64)
|
||||||
|
B = np.random.randn(N,N).astype(np.float64)
|
||||||
|
|
||||||
|
start = time.monotonic()
|
||||||
|
C = A @ B
|
||||||
|
stop = time.monotonic()
|
||||||
|
|
||||||
|
s = stop-start
|
||||||
|
|
||||||
|
ops = 2*N*N*N
|
||||||
|
|
||||||
|
print(f"NUMPY: {ops/s * 1e-9} GFLOPS\n")
|
||||||
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
#include <time.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "lina.h"
|
|
||||||
|
|
||||||
/* This program compares the lina_transpose
|
|
||||||
** implementation against the naive implementation.
|
|
||||||
** Build it with:
|
|
||||||
** $ gcc time.c lina.c -o time -Wall -Wextra -O3
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define check assert
|
|
||||||
|
|
||||||
static void naive_transpose(double *A, double *B, int m, int n)
|
|
||||||
{
|
|
||||||
assert(m > 0 && n > 0);
|
|
||||||
assert(A != NULL && B != NULL);
|
|
||||||
|
|
||||||
double *support;
|
|
||||||
|
|
||||||
if(A == B)
|
|
||||||
{
|
|
||||||
support = malloc(sizeof(*support) * m * n);
|
|
||||||
|
|
||||||
check(support != NULL);
|
|
||||||
|
|
||||||
memcpy(support, A, sizeof(*support) * m * n);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
support = A;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < n; i++)
|
|
||||||
|
|
||||||
for(int j = 0; j < m; j++)
|
|
||||||
|
|
||||||
B[j*n + i] = support[i*m + j];
|
|
||||||
|
|
||||||
if(support != A)
|
|
||||||
free(support);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap transposing functions and return their
|
|
||||||
// execution time.
|
|
||||||
static double time_transposition(void (*callback)(double*, double*, int, int), double *A, double *B, int m, int n)
|
|
||||||
{
|
|
||||||
clock_t begin = clock();
|
|
||||||
|
|
||||||
callback(A, B, m, n);
|
|
||||||
|
|
||||||
clock_t end = clock();
|
|
||||||
|
|
||||||
return (double) (end - begin) / CLOCKS_PER_SEC;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
int m = 1000;
|
|
||||||
int n = 100000;
|
|
||||||
|
|
||||||
double *big = malloc(sizeof(double) * m * n);
|
|
||||||
check(big != NULL);
|
|
||||||
|
|
||||||
memset(big, 0, sizeof(double) * m * n);
|
|
||||||
|
|
||||||
printf("lina_transpose took %gms (in-place)\n",
|
|
||||||
1000 * time_transposition(lina_transpose, big, big, m, n));
|
|
||||||
|
|
||||||
printf("naive_transpose took %gms (in-place)\n",
|
|
||||||
1000 * time_transposition(naive_transpose, big, big, m, n));
|
|
||||||
|
|
||||||
double *big2 = malloc(sizeof(double) * m * n);
|
|
||||||
check(big2 != NULL);
|
|
||||||
|
|
||||||
printf("lina_transpose took %gms\n",
|
|
||||||
1000 * time_transposition(lina_transpose, big, big2, m, n));
|
|
||||||
|
|
||||||
printf("naive_transpose took %gms\n",
|
|
||||||
1000 * time_transposition(naive_transpose, big, big2, m, n));
|
|
||||||
|
|
||||||
free(big);
|
|
||||||
free(big2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
gcc tests/test.c src/lina.c -o test -Wall -Wextra -g -Isrc/
|
|
||||||
gcc tests/test_loader.c src/lina.c -o test_loader -Wall -Wextra -g -Isrc/
|
|
||||||
+737
-294
File diff suppressed because it is too large
Load Diff
+14
-5
@@ -1,6 +1,15 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
void lina_dot(double *A, double *B, double *C, int m, int n, int l);
|
void lina_dot(double *A, double *B, double *C, int m, int n, int l);
|
||||||
void lina_add(double *A, double *B, double *C, int m, int n);
|
void lina_dot1(double *A, double *B, double *C, int m, int n, int l);
|
||||||
void lina_scale(double *A, double *B, double k, int m, int n);
|
void lina_dot2(double *A, double *B, double *C, int m, int n, int l);
|
||||||
void lina_transpose(double *A, double *B, int m, int n);
|
void lina_dot3(double *A, double *B, double *C, int m, int n, int l);
|
||||||
double *lina_loadMatrixFromStream(FILE *fp, int *width, int *height, char **error);
|
void lina_dot4(double *A, double *B, double *C, int m, int n, int l);
|
||||||
|
void lina_add(double *A, double *B, double *C, int m, int n);
|
||||||
|
void lina_scale(double *A, double *B, double k, int m, int n);
|
||||||
|
void lina_conv(double *A, double *B, double *C, int Aw, int Ah, int Bw, int Bh);
|
||||||
|
void lina_transpose(double *A, double *B, int m, int n);
|
||||||
|
bool lina_inverse(double *M, double *D, int n);
|
||||||
|
double *lina_loadMatrixFromStream(FILE *fp, int *width, int *height, char **error);
|
||||||
|
int lina_saveMatrixToStream(FILE *fp, double *A, int width, int height, char **error);
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
## Description
|
|
||||||
Here is developed the testing unit for all the lina functions that need numerical testing.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
For each function in the lina library named in the form of _lina_something()_, here is defined a folder named _something_. In each folder there are many tests, each one identified by a ti.txt file, for i=1,...,n.
|
|
||||||
Each test file is defined as follows: The first matrix/matrices are the inputs of the function (depending on the function, for example: lina_add() has two inputs A,B and one output C=A+B. A and B have to be the first two matrices in the test file), the last matrix/matrices are the output of the function and after there are input scalar values (ordered in the same order of the function under test) of the function represented as a 1x1 matrix.
|
|
||||||
|
|
||||||
For example, a scale test file, that is a test for the lina_scale() function is defined as follows:
|
|
||||||
|
|
||||||
[1 1 1,1 1 1,1 1 1]
|
|
||||||
[2 2 2,2 2 2,2 2 2]
|
|
||||||
[2]
|
|
||||||
|
|
||||||
Where the first matrix is the input, the second the output and the last is the scalar value.
|
|
||||||
|
|
||||||
By default, executing the test file will generate all the testing and provide the results on the stdout.
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
[1 0 0,
|
|
||||||
0 1 0,
|
|
||||||
0 0 1]
|
|
||||||
|
|
||||||
[1 0 0,
|
|
||||||
0 1 0,
|
|
||||||
0 0 1]
|
|
||||||
|
|
||||||
[1 0 0,
|
|
||||||
0 1 0,
|
|
||||||
0 0 1]
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
[1 1 1,
|
|
||||||
1 1 1,
|
|
||||||
1 1 1]
|
|
||||||
|
|
||||||
[2 2 2,
|
|
||||||
2 2 2,
|
|
||||||
2 2 2]
|
|
||||||
|
|
||||||
[2]
|
|
||||||
-553
@@ -1,553 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "lina.h"
|
|
||||||
|
|
||||||
#define check assert
|
|
||||||
|
|
||||||
//Print the matrix A with size m by n
|
|
||||||
static void pmatrix(FILE *fp, double *A, int m, int n);
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct dot_test{
|
|
||||||
|
|
||||||
double *A;
|
|
||||||
double *B;
|
|
||||||
double *C;
|
|
||||||
int m;
|
|
||||||
int n;
|
|
||||||
int l;
|
|
||||||
|
|
||||||
}dot_test;
|
|
||||||
|
|
||||||
typedef struct add_test{
|
|
||||||
|
|
||||||
double *A;
|
|
||||||
double *B;
|
|
||||||
double *C;
|
|
||||||
int m;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
}add_test;
|
|
||||||
|
|
||||||
typedef struct scale_test{
|
|
||||||
|
|
||||||
double *A;
|
|
||||||
double *B;
|
|
||||||
double s;
|
|
||||||
int m;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
}scale_test;
|
|
||||||
|
|
||||||
typedef struct transpose_test{
|
|
||||||
|
|
||||||
double *A;
|
|
||||||
double *B;
|
|
||||||
int m;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
}transpose_test;
|
|
||||||
|
|
||||||
#define PATH "./tests/"
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
//Defining pointers to the test structures
|
|
||||||
add_test *add_tests;
|
|
||||||
dot_test *dot_tests;
|
|
||||||
scale_test *scale_tests;
|
|
||||||
transpose_test *transpose_tests;
|
|
||||||
|
|
||||||
//Number of tests for each lina functions
|
|
||||||
int n_dot_tests, n_add_tests, n_scale_tests, n_transpose_tests;
|
|
||||||
|
|
||||||
//Opening dir stream
|
|
||||||
DIR *dir = opendir(PATH);
|
|
||||||
struct dirent *ep;
|
|
||||||
check(dir != NULL);
|
|
||||||
|
|
||||||
//Loading all the tests from files
|
|
||||||
while (ep = readdir(dir))
|
|
||||||
{
|
|
||||||
if(ep->d_type != DT_DIR || !strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(!strcmp(ep->d_name,"add"))
|
|
||||||
{
|
|
||||||
|
|
||||||
//Implement loading lina_add test matrices
|
|
||||||
char sub_path[256] = PATH;
|
|
||||||
strcat(sub_path,ep->d_name);
|
|
||||||
strcat(sub_path,"/");
|
|
||||||
|
|
||||||
DIR *sub_dir = opendir(sub_path);
|
|
||||||
check(sub_dir != NULL);
|
|
||||||
|
|
||||||
struct dirent *sub_ep;
|
|
||||||
|
|
||||||
unsigned int count = 0;
|
|
||||||
|
|
||||||
while (sub_ep = readdir(sub_dir))
|
|
||||||
{
|
|
||||||
if(sub_ep->d_type == DT_DIR)
|
|
||||||
continue;
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(sub_dir);
|
|
||||||
|
|
||||||
sub_dir = opendir(sub_path);
|
|
||||||
check(sub_dir != NULL);
|
|
||||||
|
|
||||||
add_tests = malloc(sizeof(add_test)*count);
|
|
||||||
n_add_tests = count;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (sub_ep = readdir(sub_dir))
|
|
||||||
{
|
|
||||||
if(sub_ep->d_type == DT_DIR)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
char file_pos[256];
|
|
||||||
strcat(file_pos,sub_path);
|
|
||||||
strcat(file_pos,sub_ep->d_name);
|
|
||||||
|
|
||||||
FILE *fp;
|
|
||||||
fp = fopen(file_pos,"r");
|
|
||||||
check(fp != NULL);
|
|
||||||
|
|
||||||
int m,n;
|
|
||||||
char *error;
|
|
||||||
|
|
||||||
add_tests[i].A = lina_loadMatrixFromStream(fp,&n,&m,&error);
|
|
||||||
check(add_tests[i].A != NULL);
|
|
||||||
|
|
||||||
add_tests[i].B = lina_loadMatrixFromStream(fp,&n,&m,&error);
|
|
||||||
check(add_tests[i].B != NULL);
|
|
||||||
|
|
||||||
add_tests[i].C = lina_loadMatrixFromStream(fp,&n,&m,&error);
|
|
||||||
check(add_tests[i].C != NULL);
|
|
||||||
|
|
||||||
add_tests[i].m = m;
|
|
||||||
add_tests[i].n = n;
|
|
||||||
|
|
||||||
i += 1;
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(sub_dir);
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (!strcmp(ep->d_name,"dot"))
|
|
||||||
{
|
|
||||||
//Implement loading lina_dot test matrices
|
|
||||||
char sub_path[256] = PATH;
|
|
||||||
strcat(sub_path,ep->d_name);
|
|
||||||
strcat(sub_path,"/");
|
|
||||||
|
|
||||||
DIR *sub_dir = opendir(sub_path);
|
|
||||||
check(sub_dir != NULL);
|
|
||||||
|
|
||||||
struct dirent *sub_ep;
|
|
||||||
|
|
||||||
unsigned int count = 0;
|
|
||||||
|
|
||||||
while (sub_ep = readdir(sub_dir))
|
|
||||||
{
|
|
||||||
if(sub_ep->d_type == DT_DIR)
|
|
||||||
continue;
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(sub_dir);
|
|
||||||
|
|
||||||
sub_dir = opendir(sub_path);
|
|
||||||
check(sub_dir != NULL);
|
|
||||||
dot_tests = malloc(sizeof(dot_test)*count);
|
|
||||||
n_dot_tests = count;
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (sub_ep = readdir(sub_dir))
|
|
||||||
{
|
|
||||||
if(sub_ep->d_type == DT_DIR)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
char file_pos[256];
|
|
||||||
strcpy(file_pos,sub_path);
|
|
||||||
strcat(file_pos,sub_ep->d_name);
|
|
||||||
|
|
||||||
FILE *fp;
|
|
||||||
fp = fopen(file_pos,"r");
|
|
||||||
check(fp != NULL);
|
|
||||||
|
|
||||||
int m,n,l;
|
|
||||||
char *error;
|
|
||||||
|
|
||||||
dot_tests[i].A = lina_loadMatrixFromStream(fp,&n,&m,&error);
|
|
||||||
check(dot_tests[i].A != NULL);
|
|
||||||
|
|
||||||
dot_tests[i].B = lina_loadMatrixFromStream(fp,&l,&n,&error);
|
|
||||||
check(dot_tests[i].B != NULL);
|
|
||||||
|
|
||||||
dot_tests[i].C = lina_loadMatrixFromStream(fp,&l,&m,&error);
|
|
||||||
check(dot_tests[i].C != NULL);
|
|
||||||
|
|
||||||
dot_tests[i].m = m;
|
|
||||||
dot_tests[i].n = n;
|
|
||||||
dot_tests[i].l = l;
|
|
||||||
|
|
||||||
i += 1;
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(sub_dir);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (!strcmp(ep->d_name,"scale"))
|
|
||||||
{
|
|
||||||
//Implement loading lina_scale test matrices
|
|
||||||
char sub_path[256] = PATH;
|
|
||||||
strcat(sub_path,ep->d_name);
|
|
||||||
strcat(sub_path,"/");
|
|
||||||
|
|
||||||
DIR *sub_dir = opendir(sub_path);
|
|
||||||
check(sub_dir != NULL);
|
|
||||||
|
|
||||||
struct dirent *sub_ep;
|
|
||||||
|
|
||||||
unsigned int count = 0;
|
|
||||||
|
|
||||||
while (sub_ep = readdir(sub_dir))
|
|
||||||
{
|
|
||||||
if(sub_ep->d_type == DT_DIR)
|
|
||||||
continue;
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(sub_dir);
|
|
||||||
|
|
||||||
sub_dir = opendir(sub_path);
|
|
||||||
check(sub_dir != NULL);
|
|
||||||
|
|
||||||
scale_tests = malloc(sizeof(scale_test)*count);
|
|
||||||
|
|
||||||
n_scale_tests = count;
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (sub_ep = readdir(sub_dir))
|
|
||||||
{
|
|
||||||
if(sub_ep->d_type == DT_DIR)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
char file_pos[256];
|
|
||||||
strcpy(file_pos,sub_path);
|
|
||||||
|
|
||||||
strcat(file_pos,sub_ep->d_name);
|
|
||||||
|
|
||||||
FILE *fp;
|
|
||||||
fp = fopen(file_pos,"r");
|
|
||||||
check(fp != NULL);
|
|
||||||
|
|
||||||
int m,n;
|
|
||||||
int useless1,useless2;
|
|
||||||
double *scale;
|
|
||||||
char *error;
|
|
||||||
|
|
||||||
scale_tests[i].A = lina_loadMatrixFromStream(fp,&n,&m,&error);
|
|
||||||
check(scale_tests[i].A != NULL);
|
|
||||||
|
|
||||||
scale_tests[i].B = lina_loadMatrixFromStream(fp,&n,&m,&error);
|
|
||||||
check(scale_tests[i].B != NULL);
|
|
||||||
|
|
||||||
scale = lina_loadMatrixFromStream(fp,&useless1,&useless2,&error);
|
|
||||||
check(scale != NULL);
|
|
||||||
|
|
||||||
scale_tests[i].m = m;
|
|
||||||
scale_tests[i].n = n;
|
|
||||||
scale_tests[i].s = scale[0];
|
|
||||||
free(scale);
|
|
||||||
|
|
||||||
|
|
||||||
i += 1;
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(sub_dir);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (!strcmp(ep->d_name,"transpose"))
|
|
||||||
{
|
|
||||||
//Implement loading lina_transpose test matrices
|
|
||||||
char sub_path[256] = PATH;
|
|
||||||
strcat(sub_path,ep->d_name);
|
|
||||||
strcat(sub_path,"/");
|
|
||||||
|
|
||||||
DIR *sub_dir = opendir(sub_path);
|
|
||||||
check(sub_dir != NULL);
|
|
||||||
|
|
||||||
struct dirent *sub_ep;
|
|
||||||
|
|
||||||
unsigned int count = 0;
|
|
||||||
|
|
||||||
while (sub_ep = readdir(sub_dir))
|
|
||||||
{
|
|
||||||
if(sub_ep->d_type == DT_DIR)
|
|
||||||
continue;
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(sub_dir);
|
|
||||||
|
|
||||||
sub_dir = opendir(sub_path);
|
|
||||||
check(sub_dir != NULL);
|
|
||||||
|
|
||||||
transpose_tests = malloc(sizeof(transpose_test)*count);
|
|
||||||
n_transpose_tests = count;
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (sub_ep = readdir(sub_dir))
|
|
||||||
{
|
|
||||||
if(sub_ep->d_type == DT_DIR)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
char file_pos[256];
|
|
||||||
strcpy(file_pos,sub_path);
|
|
||||||
strcat(file_pos,sub_ep->d_name);
|
|
||||||
|
|
||||||
FILE *fp;
|
|
||||||
fp = fopen(file_pos,"r");
|
|
||||||
check(fp != NULL);
|
|
||||||
|
|
||||||
int m,n;
|
|
||||||
char *error;
|
|
||||||
|
|
||||||
transpose_tests[i].A = lina_loadMatrixFromStream(fp,&n,&m,&error);
|
|
||||||
check(transpose_tests[i].A != NULL);
|
|
||||||
|
|
||||||
transpose_tests[i].B = lina_loadMatrixFromStream(fp,&m,&n,&error);
|
|
||||||
check(transpose_tests[i].B != NULL);
|
|
||||||
|
|
||||||
transpose_tests[i].m = m;
|
|
||||||
transpose_tests[i].n = n;
|
|
||||||
|
|
||||||
i += 1;
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(sub_dir);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
|
|
||||||
//Starting the lina_add tests
|
|
||||||
{
|
|
||||||
int passed_tests = 0;
|
|
||||||
fprintf(stdout,"Starting tests on lina_add():\n");
|
|
||||||
for(int i=0;i<n_add_tests;i++){
|
|
||||||
|
|
||||||
double *C = (double*) malloc(sizeof(*C)*add_tests[i].m * add_tests[i].n);
|
|
||||||
check(C != NULL);
|
|
||||||
|
|
||||||
lina_add(add_tests[i].A, add_tests[i].B, C,add_tests[i].m,add_tests[i].n);
|
|
||||||
|
|
||||||
if( !memcmp(add_tests[i].C, C, sizeof(*C)*add_tests[i].m * add_tests[i].n) )
|
|
||||||
passed_tests += 1;
|
|
||||||
else{
|
|
||||||
|
|
||||||
fprintf(stderr,"----------------------------------------------------\n");
|
|
||||||
fprintf(stderr,"Test on lina_add() failed on the following matrices:\n");
|
|
||||||
pmatrix(stderr,add_tests[i].A, add_tests[i].m, add_tests[i].n);
|
|
||||||
fprintf(stderr,"+\n");
|
|
||||||
pmatrix(stderr,add_tests[i].B, add_tests[i].m, add_tests[i].n);
|
|
||||||
fprintf(stderr,"lina_add() gives following output:\n");
|
|
||||||
pmatrix(stderr,C, add_tests[i].m, add_tests[i].n);
|
|
||||||
fprintf(stderr,"instead of:\n");
|
|
||||||
pmatrix(stderr,add_tests[i].C, add_tests[i].m, add_tests[i].n);
|
|
||||||
fprintf(stderr,"----------------------------------------------------\n");
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
free(C);
|
|
||||||
|
|
||||||
}
|
|
||||||
if(n_add_tests != 0)
|
|
||||||
fprintf(stdout, "Test on lina_add() finished: %d out of %d tests were succesfull\n",passed_tests,n_add_tests);
|
|
||||||
else
|
|
||||||
fprintf(stdout, "There are no tests for lina_add() function.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Starting the lina_dot tests
|
|
||||||
{
|
|
||||||
int passed_tests = 0;
|
|
||||||
fprintf(stdout,"\nStarting tests on lina_dot():\n");
|
|
||||||
for(int i=0;i<n_dot_tests;i++){
|
|
||||||
|
|
||||||
double *C = (double*) malloc(sizeof(*C)*dot_tests[i].m * dot_tests[i].l);
|
|
||||||
check(C != NULL);
|
|
||||||
|
|
||||||
lina_dot(dot_tests[i].A, dot_tests[i].B, C, dot_tests[i].m, dot_tests[i].n, dot_tests[i].l);
|
|
||||||
|
|
||||||
if( !memcmp(dot_tests[i].C, C, sizeof(*C)*dot_tests[i].m * dot_tests[i].l) )
|
|
||||||
passed_tests += 1;
|
|
||||||
else{
|
|
||||||
|
|
||||||
fprintf(stderr,"----------------------------------------------------\n");
|
|
||||||
fprintf(stderr,"Test on lina_dot() failed on the following matrices:\n");
|
|
||||||
pmatrix(stderr,dot_tests[i].A, dot_tests[i].m, dot_tests[i].n);
|
|
||||||
fprintf(stderr,"*\n");
|
|
||||||
pmatrix(stderr,dot_tests[i].B, dot_tests[i].n, dot_tests[i].l);
|
|
||||||
fprintf(stderr,"lina_dot() gives following output:\n");
|
|
||||||
pmatrix(stderr,C, dot_tests[i].m, dot_tests[i].l);
|
|
||||||
fprintf(stderr,"instead of:\n");
|
|
||||||
pmatrix(stderr,dot_tests[i].C, dot_tests[i].m, dot_tests[i].l);
|
|
||||||
fprintf(stderr,"----------------------------------------------------\n");
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
free(C);
|
|
||||||
|
|
||||||
}
|
|
||||||
if(n_dot_tests != 0)
|
|
||||||
fprintf(stdout, "Test on lina_dot() finished: %d out of %d tests were succesfull\n",passed_tests,n_dot_tests);
|
|
||||||
else
|
|
||||||
fprintf(stdout, "There are no tests for lina_dot() function.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Starting the lina_transpose tests
|
|
||||||
{
|
|
||||||
int passed_tests = 0;
|
|
||||||
fprintf(stdout,"\nStarting tests on lina_transpose():\n");
|
|
||||||
for(int i=0;i<n_transpose_tests;i++){
|
|
||||||
|
|
||||||
double *C = (double*) malloc(sizeof(*C)*transpose_tests[i].m * transpose_tests[i].n);
|
|
||||||
check(C != NULL);
|
|
||||||
|
|
||||||
lina_transpose(transpose_tests[i].A, C, transpose_tests[i].m, transpose_tests[i].n);
|
|
||||||
|
|
||||||
if( !memcmp(transpose_tests[i].B, C, sizeof(*C)*transpose_tests[i].m * transpose_tests[i].n) )
|
|
||||||
passed_tests += 1;
|
|
||||||
else{
|
|
||||||
|
|
||||||
fprintf(stderr,"----------------------------------------------------\n");
|
|
||||||
fprintf(stderr,"Test on lina_transpose() failed on the following matrices:\n");
|
|
||||||
pmatrix(stderr,transpose_tests[i].A, transpose_tests[i].m, transpose_tests[i].n);
|
|
||||||
fprintf(stderr,"lina_transpose() gives following output:\n");
|
|
||||||
pmatrix(stderr,C, transpose_tests[i].n, transpose_tests[i].m);
|
|
||||||
fprintf(stderr,"instead of:\n");
|
|
||||||
pmatrix(stderr,transpose_tests[i].B, transpose_tests[i].n, transpose_tests[i].m);
|
|
||||||
fprintf(stderr,"----------------------------------------------------\n");
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
free(C);
|
|
||||||
|
|
||||||
}
|
|
||||||
if(n_transpose_tests != 0)
|
|
||||||
fprintf(stdout, "Test on lina_transpose() finished: %d out of %d tests were succesfull\n",passed_tests,n_transpose_tests);
|
|
||||||
else
|
|
||||||
fprintf(stdout, "There are no tests for lina_transpose() function.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Starting the lina_scale tests
|
|
||||||
{
|
|
||||||
int passed_tests = 0;
|
|
||||||
fprintf(stdout,"\nStarting tests on lina_scale():\n");
|
|
||||||
for(int i=0;i<n_scale_tests;i++){
|
|
||||||
|
|
||||||
double *C = (double*) malloc(sizeof(*C)*scale_tests[i].m * scale_tests[i].n);
|
|
||||||
check(C != NULL);
|
|
||||||
|
|
||||||
lina_scale(scale_tests[i].A, C, scale_tests[i].s, scale_tests[i].m, scale_tests[i].n);
|
|
||||||
|
|
||||||
if( !memcmp(scale_tests[i].B, C, sizeof(*C)*scale_tests[i].m * scale_tests[i].n) )
|
|
||||||
passed_tests += 1;
|
|
||||||
else{
|
|
||||||
|
|
||||||
fprintf(stderr,"----------------------------------------------------\n");
|
|
||||||
fprintf(stderr,"Test on lina_scale() failed on the following matrices:\n");
|
|
||||||
pmatrix(stderr,scale_tests[i].A, scale_tests[i].m, scale_tests[i].n);
|
|
||||||
fprintf(stderr,"lina_scale() gives following output:\n");
|
|
||||||
pmatrix(stderr, C, scale_tests[i].m, scale_tests[i].n);
|
|
||||||
fprintf(stderr,"instead of:\n");
|
|
||||||
pmatrix(stderr,scale_tests[i].B, scale_tests[i].m, scale_tests[i].n);
|
|
||||||
fprintf(stderr,"----------------------------------------------------\n");
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
free(C);
|
|
||||||
|
|
||||||
}
|
|
||||||
if(n_scale_tests != 0)
|
|
||||||
fprintf(stdout, "Test on lina_scale() finished: %d out of %d tests were succesfull\n",passed_tests,n_scale_tests);
|
|
||||||
else
|
|
||||||
fprintf(stdout, "There are no tests for lina_scale() function.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Freeing the memory of all the heap variables
|
|
||||||
{
|
|
||||||
//Freeing add_tests memory
|
|
||||||
for(int i=0;i< n_add_tests;i++)
|
|
||||||
{
|
|
||||||
free(add_tests[i].A);
|
|
||||||
free(add_tests[i].B);
|
|
||||||
free(add_tests[i].C);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Freeing dot_tests memory
|
|
||||||
for(int i=0;i< n_dot_tests;i++)
|
|
||||||
{
|
|
||||||
free(dot_tests[i].A);
|
|
||||||
free(dot_tests[i].B);
|
|
||||||
free(dot_tests[i].C);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Freeing scale_tests memory
|
|
||||||
for(int i=0;i< n_scale_tests;i++)
|
|
||||||
{
|
|
||||||
free(scale_tests[i].A);
|
|
||||||
free(scale_tests[i].B);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Freeing transpose_tests memory
|
|
||||||
for(int i=0;i< n_transpose_tests;i++)
|
|
||||||
{
|
|
||||||
free(transpose_tests[i].A);
|
|
||||||
free(transpose_tests[i].B);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pmatrix(FILE *fp, double *A,int m,int n){
|
|
||||||
|
|
||||||
for(int i = 0; i<m; i++){
|
|
||||||
fprintf(fp, " | ");
|
|
||||||
for(int j = 0; j< n; j++)
|
|
||||||
fprintf(fp, "%g ",A[i*n + j]);
|
|
||||||
|
|
||||||
fprintf(fp, "|\n");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
[1 0 0 0,
|
|
||||||
0 2 0 0,
|
|
||||||
0 0 3 0,
|
|
||||||
0 0 0 4]
|
|
||||||
|
|
||||||
[1 0 0 0,
|
|
||||||
0 2 0 0,
|
|
||||||
0 0 3 0,
|
|
||||||
0 0 0 4]
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
[1 2,
|
|
||||||
3 4,
|
|
||||||
5 6]
|
|
||||||
|
|
||||||
[1 3 5,
|
|
||||||
2 4 6]
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
[1 2 3 4,
|
|
||||||
0 0 0 0,
|
|
||||||
0 0 0 0,
|
|
||||||
0 0 0 0]
|
|
||||||
|
|
||||||
[1 0 0 0,
|
|
||||||
2 0 0 0,
|
|
||||||
3 0 0 0,
|
|
||||||
4 0 0 0]
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
[0 1 0 0,
|
|
||||||
0 2 0 0,
|
|
||||||
0 3 0 0,
|
|
||||||
0 4 0 0]
|
|
||||||
|
|
||||||
[0 0 0 0,
|
|
||||||
1 2 3 4,
|
|
||||||
0 0 0 0,
|
|
||||||
0 0 0 0]
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
[0 0 1 0,
|
|
||||||
0 0 2 0,
|
|
||||||
0 0 3 0,
|
|
||||||
0 0 4 0]
|
|
||||||
|
|
||||||
[0 0 0 0,
|
|
||||||
0 0 0 0,
|
|
||||||
1 2 3 4,
|
|
||||||
0 0 0 0]
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
[0 0 0 0,
|
|
||||||
0 0 0 0,
|
|
||||||
0 0 0 0,
|
|
||||||
1 2 3 4]
|
|
||||||
|
|
||||||
[0 0 0 1,
|
|
||||||
0 0 0 2,
|
|
||||||
0 0 0 3,
|
|
||||||
0 0 0 4]
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
[1 0 0,
|
|
||||||
0 2 0,
|
|
||||||
0 0 3]
|
|
||||||
|
|
||||||
[1 0 0,
|
|
||||||
0 2 0,
|
|
||||||
0 0 3]
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
[1 2 3,
|
|
||||||
0 0 0,
|
|
||||||
0 0 0]
|
|
||||||
|
|
||||||
[1 0 0,
|
|
||||||
2 0 0,
|
|
||||||
3 0 0]
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
[0 0 1,
|
|
||||||
0 0 2,
|
|
||||||
0 0 3]
|
|
||||||
|
|
||||||
[0 0 0,
|
|
||||||
0 0 0,
|
|
||||||
1 2 3]
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
[1 2 3,
|
|
||||||
4 5 6]
|
|
||||||
|
|
||||||
[1 4,
|
|
||||||
2 5,
|
|
||||||
3 6]
|
|
||||||
Reference in New Issue
Block a user