changed curly bracket code style

This commit is contained in:
Francesco Cozzuto
2023-03-30 01:25:07 +02:00
parent 4d35b7d8de
commit 85f5fc43d7
2 changed files with 275 additions and 317 deletions
+2 -4
View File
@@ -1,4 +1,2 @@
# 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!
Note that this is still a work in progress.
+252 -292
View File
@@ -29,36 +29,28 @@
** - This function can never fail. ** - This function can never fail.
*/ */
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)
{
lina_dot2(A, B, C, 0, 0, 0, m, n, l);
}
void lina_dot2(double *A, double *B, double *C,
int As, int Bs, int Cs,
int m, int n, int l)
{ {
assert(m > 0 && n > 0 && l > 0); assert(m > 0 && n > 0 && l > 0);
assert(As >= 0 && Bs >= 0 && Cs >= 0);
assert(A != NULL && B != NULL && C != NULL); assert(A != NULL && B != NULL && C != NULL);
assert(A != C && B != C); assert(A != C && B != C);
// Iteration over A's rows // Iteration over A's rows
for(int i = 0; i < m; i++) for(int i = 0; i < m; i++) {
{
// Iteration over B's columns
for(int k = 0; k < l; k++)
{
double pos = 0;
// Iteration over the single B column // Iteration over B's columns
// for executing the product of sum for(int k = 0; k < l; k++) {
for(int j=0; j < n; j++) double sum = 0;
pos += A[i*(n + As) + j] * B[j*(l + Bs) + k];
C[i*(l + Cs) + k] = pos; // Iteration over the single B column
} // for executing the product of sum
for(int j=0; j < n; j++)
sum += A[i * n + j] * B[j * l + k];
C[i * l + k] = sum;
} }
}
} }
/* Function: lina_add /* Function: lina_add
@@ -130,68 +122,64 @@ void lina_transpose(double *A, double *B, int m, int n)
assert(m > 0 && n > 0); assert(m > 0 && n > 0);
assert(A != NULL && B != NULL); assert(A != NULL && B != NULL);
if(m == 1 || n == 1) if(m == 1 || n == 1) {
{ // For a matrix with height or width of 1
// For a matrix with height or width of 1 // row-major and column-major order coincide,
// row-major and column-major order coincide, // so the stransposition doesn't change the
// so the stransposition doesn't change the // the memory representation. A simple copy
// the memory representation. A simple copy // does the job.
// does the job.
if(A != B) // Does the copy or the branch cost more? if(A != B) // Does the copy or the branch cost more?
memcpy(B, A, sizeof(A[0]) * m * n); memcpy(B, A, sizeof(A[0]) * m * n);
} else if(m == n) {
// Iterate over the upper triangular portion of
// the matrix and switch each element with the
// corresponding one in the lower triangular portion.
// NOTE: We're assuming A,B might be the same matrix.
// If A,B are the same matrix, then the diagonal
// is copied onto itself. By removing the +1 in
// the inner loop, the copying of the diagonal
// is avoided.
for(int i = 0; i < n; i += 1)
for(int j = 0; j < i+1; j += 1) {
double temp = A[i*n + j];
B[i*n + j] = A[j*n + i];
B[j*n + i] = temp;
}
} else {
// Not only the matrix needs to be transposed
// assuming the destination matrix is the same
// as the source matrix, but the memory representation
// of the matrix needs to switch from row-major
// to col-major, so it's not as simple as switching
// value's positions.
// This algorithm starts from the A[0][1] value and
// moves it where it needs to go, then gets the value
// that was at that position and puts that in it's
// new position. This process is iterated until the
// starting point A[0][1] is overwritten with the
// new value. In this process the first and last
// value of the matrix never move.
B[0] = A[0];
B[m*n - 1] = A[m*n - 1];
double item = A[1];
int next = m;
while(next != 1) {
double temp = A[next];
B[next] = item;
item = temp;
next = (next % n) * m + (next / n);
} }
else if(m == n)
{
// Iterate over the upper triangular portion of
// the matrix and switch each element with the
// corresponding one in the lower triangular portion.
// NOTE: We're assuming A,B might be the same matrix.
// If A,B are the same matrix, then the diagonal
// is copied onto itself. By removing the +1 in
// the inner loop, the copying of the diagonal
// is avoided.
for(int i = 0; i < n; i += 1) B[1] = item;
for(int j = 0; j < i+1; j += 1) }
{
double temp = A[i*n + j];
B[i*n + j] = A[j*n + i];
B[j*n + i] = temp;
}
}
else
{
// Not only the matrix needs to be transposed
// assuming the destination matrix is the same
// as the source matrix, but the memory representation
// of the matrix needs to switch from row-major
// to col-major, so it's not as simple as switching
// value's positions.
// This algorithm starts from the A[0][1] value and
// moves it where it needs to go, then gets the value
// that was at that position and puts that in it's
// new position. This process is iterated until the
// starting point A[0][1] is overwritten with the
// new value. In this process the first and last
// value of the matrix never move.
B[0] = A[0];
B[m*n - 1] = A[m*n - 1];
double item = A[1];
int next = m;
while(next != 1)
{
double temp = A[next];
B[next] = item;
item = temp;
next = (next % n) * m + (next / n);
}
B[1] = item;
}
} }
/* Function: scanValue /* Function: scanValue
@@ -241,22 +229,19 @@ static int scanValue(FILE *fp, char *buffer, int max_length, char first, char *f
// Scan the integer portion of // Scan the integer portion of
// the numeric value and copy it // the numeric value and copy it
// into the buffer. // into the buffer.
do do {
{
if(n == max_length)
{
// ERROR: Internal buffer is too small to hold
// the representation of this item.
*error = "Internal buffer is too small to hold "
"the representation of a numeric value";
return 0;
}
buffer[n++] = c; if(n == max_length) {
*error = "Internal buffer is too small to hold "
c = getc(fp); "the representation of a numeric value";
return 0;
} }
while(c != EOF && isdigit(c));
buffer[n++] = c;
c = getc(fp);
} while(c != EOF && isdigit(c));
// Did the integer part end with // Did the integer part end with
// a dot? // a dot?
@@ -265,48 +250,42 @@ static int scanValue(FILE *fp, char *buffer, int max_length, char first, char *f
// Now scan and copy the decimal // Now scan and copy the decimal
// part of the numeric value if // part of the numeric value if
// a dot was found. // a dot was found.
if(dot) if(dot) {
{ if(n == max_length) {
if(n == max_length) // ERROR: Internal buffer is too small to hold
{ // the representation of this item.
// ERROR: Internal buffer is too small to hold // (The dot doesn't fit.)
// the representation of this item. *error = "Internal buffer is too small to hold "
// (The dot doesn't fit.) "the representation of a numeric value";
*error = "Internal buffer is too small to hold " return 0;
"the representation of a numeric value"; }
return 0;
}
buffer[n++] = '.'; buffer[n++] = '.';
c = getc(fp);
if(!isdigit(c)) {
// ERROR: Got something other than a
// digit after the dot.
*error = "Got something other than a digit after the dot.";
return 0;
}
do {
if(n == max_length) {
// ERROR: Internal buffer is too small
// to hold the representation of
// this item.
*error = "Internal buffer is too small to hold "
"the representation of a numeric value";
return 0;
}
buffer[n++] = c;
c = getc(fp); c = getc(fp);
} while(c != EOF && isdigit(c));
if(!isdigit(c)) }
{
// ERROR: Got something other than a
// digit after the dot.
*error = "Got something other than a digit after the dot.";
return 0;
}
do
{
if(n == max_length)
{
// ERROR: Internal buffer is too small
// to hold the representation of
// this item.
*error = "Internal buffer is too small to hold "
"the representation of a numeric value";
return 0;
}
buffer[n++] = c;
c = getc(fp);
}
while(c != EOF && isdigit(c));
}
buffer[n] = '\0'; buffer[n] = '\0';
@@ -377,23 +356,21 @@ double *lina_loadMatrixFromStream(FILE *fp, int *width, int *height, char **erro
while(c != EOF && isspace(c)) while(c != EOF && isspace(c))
c = getc(fp); c = getc(fp);
if(c == EOF) if(c == EOF) {
{ // ERROR: Stream ended before a matrix was
// ERROR: Stream ended before a matrix was // found.
// found. *error = "Stream ended before a matrix was found";
*error = "Stream ended before a matrix was found"; return NULL;
return NULL; }
}
if(c != '[') if(c != '[') {
{ // ERROR: Was expected a '[' as the first
// ERROR: Was expected a '[' as the first // character of a matrix, but got
// character of a matrix, but got // something else instead.
// something else instead. *error = "Got something other than a matrix "
*error = "Got something other than a matrix " "where one was expected";
"where one was expected"; return NULL;
return NULL; }
}
c = getc(fp); c = getc(fp);
@@ -401,173 +378,161 @@ double *lina_loadMatrixFromStream(FILE *fp, int *width, int *height, char **erro
while(c != EOF && isspace(c)) while(c != EOF && isspace(c))
c = getc(fp); c = getc(fp);
if(c == EOF) if(c == EOF) {
{ // ERROR: Stream ended where a numeric value
// ERROR: Stream ended where a numeric value // was expected.
// was expected. *error = "Stream ended where a numeric value "
*error = "Stream ended where a numeric value " "was expected";
"was expected"; return NULL;
return NULL; }
}
double *matrix = malloc(sizeof(matrix[0]) * 64); double *matrix = malloc(sizeof(matrix[0]) * 64);
if(matrix == NULL) if(matrix == NULL) {
{ // ERROR: Insufficient memory.
// ERROR: Insufficient memory. *error = "Insufficient memory";
*error = "Insufficient memory"; return NULL;
return NULL; }
}
int capacity = 64, size = 0, int capacity = 64, size = 0,
w = -1, i = 0, j = 0; w = -1, i = 0, j = 0;
if(c != ']') if(c != ']')
while(1) while(1) {
{ if(!isdigit(c)) {
if(!isdigit(c)) // ERROR: Got something other than a digit
{ // where a numeric value was expected.
// ERROR: Got something other than a digit *error = "Got something other than a numeric "
// where a numeric value was expected. "value where one was expected";
*error = "Got something other than a numeric " return NULL;
"value where one was expected"; }
return NULL;
}
// Numeric values can't be represented // Numeric values can't be represented
// in strings bigger than this buffer // in strings bigger than this buffer
// since they need to be copied in it // since they need to be copied in it
// to be converted to actual numeric // to be converted to actual numeric
// variables. // variables.
char buffer[128]; char buffer[128];
int res = scanValue(fp, buffer, sizeof(buffer), c, &c, error); int res = scanValue(fp, buffer, sizeof(buffer), c, &c, error);
if(res == 0) if(res == 0)
// Failed to scan the value, abort. // Failed to scan the value, abort.
// NOTE: The error was already reported. // NOTE: The error was already reported.
return NULL;
assert(res == 1 || res == -1);
// Make sure the matrix has enough space.
if(size == capacity) {
int new_capacity = capacity * 2;
double *temp = realloc(matrix, sizeof(double) * new_capacity);
if(temp == NULL) {
// ERROR: Insufficient memory.
*error = "Insufficient memory";
free(matrix);
return NULL; return NULL;
}
assert(res == 1 || res == -1); matrix = temp;
capacity = new_capacity;
}
// Make sure the matrix has enough space. errno = 0;
if(size == capacity)
{
int new_capacity = capacity * 2;
double *temp = realloc(matrix, sizeof(double) * new_capacity); double casted;
if(temp == NULL) if(res == 1)
{ casted = (double) strtoll(buffer, NULL, 10);
// ERROR: Insufficient memory. else
*error = "Insufficient memory"; casted = strtod(buffer, NULL);
free(matrix);
return NULL;
}
matrix = temp; if(errno) {
capacity = new_capacity; // ERROR: Failed to convert a numeric value
} // from it's string form to a numeric
// variable.
*error = "Failed to convert string to number";
free(matrix);
return NULL;
}
errno = 0; matrix[size++] = casted;
double casted; i += 1;
if(res == 1) while(c != EOF && isspace(c))
casted = (double) strtoll(buffer, NULL, 10); c = getc(fp);
else
casted = strtod(buffer, NULL);
if(errno) if(c == ']' || c == ',') {
{ // The matrix's row just ended.
// ERROR: Failed to convert a numeric value
// from it's string form to a numeric if(w == -1)
// variable. // This was the first row.
*error = "Failed to convert string to number"; w = i;
free(matrix); else {
// This wasn't the first row,
// so it's possible that it's
// length is different from the
// previous ones.
assert(w > -1);
if(i != w) {
// ERROR: The j-th row has the wrong
// number of elements.
if(i < w)
*error = "Matrix row is too short";
else
*error = "Matrix row is too long";
return NULL; return NULL;
} }
}
matrix[size++] = casted; i = 0;
j += 1;
i += 1; if(c == ']')
// The whole matrix ended!
break;
c = getc(fp);
while(c != EOF && isspace(c)) while(c != EOF && isspace(c))
c = getc(fp); c = getc(fp);
if(c == ']' || c == ',')
{
// The matrix's row just ended.
if(w == -1)
// This was the first row.
w = i;
else
{
// This wasn't the first row,
// so it's possible that it's
// length is different from the
// previous ones.
assert(w > -1);
if(i != w)
{
// ERROR: The j-th row has the wrong
// number of elements.
if(i < w)
*error = "Matrix row is too short";
else
*error = "Matrix row is too long";
return NULL;
}
}
i = 0;
j += 1;
if(c == ']')
// The whole matrix ended!
break;
c = getc(fp);
while(c != EOF && isspace(c))
c = getc(fp);
}
if(c == EOF)
{
// ERROR: Stream ended inside a matrix, where
// either ',', ']' or a numeric value was
// expected.
*error = "Stream ended inside a matrix, where either "
"',', ']' or a numeric value was expected";
return NULL;
}
} }
if(size == 0) if(c == EOF) {
{ // ERROR: Stream ended inside a matrix, where
free(matrix); // either ',', ']' or a numeric value was
*error = "Empty matrix"; // expected.
return NULL; *error = "Stream ended inside a matrix, where either "
"',', ']' or a numeric value was expected";
return NULL;
}
} }
if(size == 0) {
free(matrix);
*error = "Empty matrix";
return NULL;
}
// If the internal fragmentation is too much, // If the internal fragmentation is too much,
// return a dynamic memory region with the // return a dynamic memory region with the
// exact size instead of the buffer used to // exact size instead of the buffer used to
// build the matrix. // build the matrix.
int fragm_threshold = 30; // (It's a percentage) int fragm_threshold = 30; // (It's a percentage)
if(100.0 * size/capacity < fragm_threshold) if(100.0 * size/capacity < fragm_threshold) {
{
int new_capacity = (size == 0) ? 1 : size;
double *temp = realloc(matrix, new_capacity * sizeof(double)); int new_capacity = (size == 0) ? 1 : size;
if(temp != NULL) double *temp = realloc(matrix, new_capacity * sizeof(double));
matrix = temp;
} if(temp != NULL)
matrix = temp;
}
*width = w; *width = w;
*height = j; *height = j;
@@ -613,14 +578,12 @@ int lina_saveMatrixToStream(FILE *fp, double *A, int width, int height, char **e
else else
*error = NULL; *error = NULL;
if (width < 1) if (width < 1) {
{
*error = "The provided width is less than one"; *error = "The provided width is less than one";
return -1; return -1;
} }
if (height < 1) if (height < 1) {
{
*error = "The provided height is less than one"; *error = "The provided height is less than one";
return -1; return -1;
} }
@@ -630,19 +593,17 @@ int lina_saveMatrixToStream(FILE *fp, double *A, int width, int height, char **e
putc('[',fp); putc('[',fp);
for (int i = 0; i < height-1; i++) for (int i = 0; i < height-1; i++) {
{
for (int j = 0; j < width-1; j++) for (int j = 0; j < width-1; j++)
fprintf(fp, "%f ", A[i*width + j]); fprintf(fp, "%f ", A[i*width + j]);
fprintf(fp, "%f, ", A[i*width + width-1]); fprintf(fp, "%f, ", A[i*width + width-1]);
} }
for (int j = 0; j < width-1; j++) for (int j = 0; j < width-1; j++)
fprintf(fp, "%f ", A[(height-1)*width + j]); fprintf(fp, "%f ", A[(height-1)*width + j]);
fprintf(fp, "%f", A[(height-1)*width + width-1]); fprintf(fp, "%f", A[(height-1)*width + width-1]);
putc(']',fp); putc(']',fp);
@@ -666,17 +627,16 @@ void lina_conv(double *A, double *B, double *C,
// Iterate over each pixel of the result matrix.. // Iterate over each pixel of the result matrix..
for(int j = 0; j < Ch; j += 1) for(int j = 0; j < Ch; j += 1)
for(int i = 0; i < Cw; i += 1) for(int i = 0; i < Cw; i += 1) {
{ // ..and calculate it's value as
// ..and calculate it's value as // the scalar product between the
// the scalar product between the // mask B and a portion of A.
// mask B and a portion of A.
C[j * Cw + i] = 0; C[j * Cw + i] = 0;
for(int v = 0; v < Bh; v += 1) for(int v = 0; v < Bh; v += 1)
for(int u = 0; u < Bw; u += 1) for(int u = 0; u < Bw; u += 1)
C[j * Cw + i] += A[(i - Bw/2 + u) * Aw + (i - Bh/2 + v)] * B[v * Bw + u]; C[j * Cw + i] += A[(i - Bw/2 + u) * Aw + (i - Bh/2 + v)] * B[v * Bw + u];
} }
} }
void lina_reallyP(int *P, double *P2, int n) void lina_reallyP(int *P, double *P2, int n)