I have written the following function in C
double * transpose(double *M, int n) {
double *T = (double *) malloc(n * n * sizeof(double));
int i, j;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
T[i + (j * n)] = M[(i * n) + j];
}
}
return T;
}
and I call it as such:
C = transpose(C, n);
where C was previously declared as
double *C = (double *) malloc(n * n * sizeof(double));
and then initialised with values.
How can I, instead of returning T, set my function type to void and then call the equivalent of *M = *T instead of my return statement. In other words, how can I call the function like:
transpose(C, n);
so that *C is pointing to the memory allocation created by *T?
EDIT:
As pointed out by wildplasser below, a more efficient way of transposing the matrix in place would be swapping the {i, j} pairs except along the diagonal.
Something along the lines of this:
void * transpose(double *M, int n) {
int i, j;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
if (i != j) {
double temp = M[i + (j * n)];
M[i + (j * n)] = M[(i * n) + j];
M[(i * n) + j] = temp;
}
}
}
}
However, calling this as
transpose(C, n);
does not allow C to keep it's transposition after the function. What am I doing wrong here?
Also GCC is giving me the warning
Utilities.c: In function 'transpose':
Utilities.c:34:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
I have defined my function as void in both the header and source file?
void transpose(double *arr, size_t siz)
{
size_t ii,jj;
for(ii=0;ii<siz;ii++) {
for(jj=ii+1;jj<siz;jj++){
double tmp;
size_t aa,bb;
aa = ii+ siz * jj;
bb = jj+ siz * ii;
tmp = arr[aa];
arr[aa] = arr[bb];
arr[bb] = tmp;
}
}
}
Don't worry about theaa and bb variables. Any decent compiler will optimize them away.
First of all, your code has a memory leak. You overwrite the previous value of C without ever freeing it.
To transpose in place, you need to just swap all the right indexes without swapping twice. So it's like the same problem as reversing an array in place.
void transpose(double *M, int n) {
int i, j;
double temp;
for(i = 0; i < n; i++) {
for(j = 0; j < i; j++) {
temp = M[i + j * n];
M[i + j * n] = M[j + i * n];
M[j + i * n] = temp;
}
}
}
void transpose(double **C, double *M, int n) {
double *T = (double *) malloc(n * n * sizeof(double));
int i, j;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
T[i + (j * n)] = M[(i * n) + j];
}
}
*C = T;
}
And call your function like this :
transpose(&C, n);
As the comments suggest free the old C before to avoid memory leak
Related
I'm trying to write a function that does naive matrix multiplication of two contiguous, row-major arrays. But when I attempt to print each value at the end I get garbage. I'm guessing it's because I've mixed up the proper iterations and scaling needed to jump rows/columns. Does anyone have any advice?
Full code necessary is below:
#include <stdio.h>
#include <stdlib.h>
void dmatmul(double *a, double *b, double *c, int astride, int bstride, int cdim_0, int cdim_1) {
int i, j, p;
for (i = 0; i < cdim_0; i++) {
for (j = 0; j < cdim_1; j++) {
c[i * cdim_1 + j] = 0.0;
for (p = 0; p < (astride); p++) {
c[i * cdim_1 + j] += a[i * (astride) + p] * b[p * (bstride) + j];
}
}
}
}
int main(void) {
double *x, *y, *z;
int xdim_0, xdim_1, ydim_0, ydim_1, zdim_0, zdim_1, i, j;
xdim_0 = 2;
xdim_1 = 4;
ydim_0 = 4;
ydim_1 = 2;
zdim_0 = 2;
zdim_1 = 2;
x = (double *) malloc (xdim_0 * xdim_1 * sizeof(double));
y = (double *) malloc (ydim_0 * ydim_1 * sizeof(double));
z = (double *) malloc (zdim_0 * zdim_1 * sizeof(double));
for (i = 0; i < xdim_0 * xdim_1; i++) {
x[i] = i + 1;
y[i] = 2 * (i + 1);
}
dmatmul(x, y, z, xdim_1, ydim_1, zdim_0, zdim_1);
printf("\nMatrix product of X and Y dimensions: (%d, %d)\n", zdim_0, zdim_1);
printf("Matrix product of X and Y values:");
for (i = 0; i < zdim_0; i++) {
printf("\n");
for (j = 0; j < zdim_1; i++) {
printf("\t%f", z[i * zdim_1 + j]);
}
}
return 0;
}
The primary problem is a typo in the inner for loop doing the printing. You have:
for (j = 0; j < zdim_1; i++)
but you ned to increment j, not i:
for (j = 0; j < zdim_1; j++)
Here's my code, which has an independent matrix printing function appropriate for the arrays you're using:
/* SO 7516-7451 */
#include <stdio.h>
#include <stdlib.h>
static void dmatmul(double *a, double *b, double *c, int astride, int bstride, int cdim_0, int cdim_1)
{
int i, j, p;
for (i = 0; i < cdim_0; i++)
{
for (j = 0; j < cdim_1; j++)
{
c[i * cdim_1 + j] = 0.0;
for (p = 0; p < (astride); p++)
{
c[i * cdim_1 + j] += a[i * (astride) + p] * b[p * (bstride) + j];
}
}
}
}
static void mat_print(const char *tag, int rows, int cols, double *matrix)
{
printf("%s (%dx%d):\n", tag, rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
printf("%4.0f", matrix[i * cols + j]);
putchar('\n');
}
}
int main(void)
{
int xdim_0 = 2;
int xdim_1 = 4;
int ydim_0 = 4;
int ydim_1 = 2;
int zdim_0 = 2;
int zdim_1 = 2;
double *x = (double *)malloc(xdim_0 * xdim_1 * sizeof(double));
double *y = (double *)malloc(ydim_0 * ydim_1 * sizeof(double));
double *z = (double *)malloc(zdim_0 * zdim_1 * sizeof(double));
for (int i = 0; i < xdim_0 * xdim_1; i++)
{
x[i] = i + 1;
y[i] = 2 * (i + 1);
}
mat_print("X", xdim_0, xdim_1, x);
mat_print("Y", ydim_0, ydim_1, y);
dmatmul(x, y, z, xdim_1, ydim_1, zdim_0, zdim_1);
mat_print("Z", zdim_0, zdim_1, z);
printf("\nMatrix product of X and Y dimensions: (%d, %d)\n", zdim_0, zdim_1);
printf("Matrix product of X and Y values:\n");
for (int i = 0; i < zdim_0; i++)
{
for (int j = 0; j < zdim_1; j++)
printf("\t%f", z[i * zdim_1 + j]);
printf("\n");
}
return 0;
}
I've also initialized the variables as I declared them. The code should, but does not, check that the memory was allocated.
When I ran this code without your printing, I got the correct result, so then I took a good look at that and saw the problem.
X (2x4):
1 2 3 4
5 6 7 8
Y (4x2):
2 4
6 8
10 12
14 16
Z (2x2):
100 120
228 280
Matrix product of X and Y dimensions: (2, 2)
Matrix product of X and Y values:
100.000000 120.000000
228.000000 280.000000
I have a task where I'm supposed to multiply two quadratic matrices of size n in C, using pointers as function parameters and return value. This is the given function head: int** multiply(int** a, int** b, int n). Normally, I would use three arrays (the two matrices and the result) as parameters, but since I had to do it this way, this is what I came up with:
#include <stdio.h>
#include <stdlib.h>
int** multiply(int** a, int** b, int n) {
int **c = malloc(sizeof(int) * n * n);
// Rows of c
for (int i = 0; i < n; i++) {
// Columns of c
for (int j = 0; j < n; j++) {
// c[i][j] = Row of a * Column of b
for (int k = 0; i < n; k++) {
*(*(c + i) + j) += *(*(a + i) + k) * *(*(b + k) + j);
}
}
}
return c;
}
int main() {
int **a = malloc(sizeof(int) * 2 * 2);
int **b = malloc(sizeof(int) * 2 * 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; i < 2; j++) {
*(*(a + i) + j) = i - j;
*(*(b + i) + j) = j - i;
}
}
int **c = multiply(a, b, 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("c[%d][%d] = %d\n", i, j, c[i][j]);
}
}
free(a);
free(b);
free(c);
return 0;
}
I have not worked much with pointers before, and am generally new to C, so I have no idea why this doesn't work or what I'd have to do instead. The error I'm getting when trying to run this program is segmentation fault (core dumped). I don't even know exactly what that means... :(
Can someone please help me out?
There's lots of fundamental problems in the code. Most notably, int** is not a 2D array and cannot point at one.
i<2 typo in the for(int j... loop.
i < n in the for(int k... loop.
To allocate a 2D array you must do: int (*a)[2] = malloc(sizeof(int) * 2 * 2);. Or if you will malloc( sizeof(int[2][2]) ), same thing.
To access a 2D array you do a[i][j].
To pass a 2D array to a function you do void func (int n, int arr[n][n]);
Returning a 2D array from a function is trickier, easiest for now is just to use void* and get that working.
malloc doesn't initialize the allocated memory. If you want to do += on c you should use calloc instead, to set everything to zero.
Don't write an unreadable mess like *(*(c + i) + j). Write c[i][j].
I fixed these problems and got something that runs. You check if the algorithm is correct from there.
#include <stdio.h>
#include <stdlib.h>
void* multiply(int n, int a[n][n], int b[n][n]) {
int (*c)[n] = calloc(1, sizeof(int[n][n]));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
c[i][j] += a[i][k] * b[k][j];
}
}
}
return c;
}
int main() {
int (*a)[2] = malloc(sizeof(int[2][2]));
int (*b)[2] = malloc(sizeof(int[2][2]));
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
a[i][j] = i - j;
b[i][j] = j - i;
}
}
int (*c)[2] = multiply(2, a, b);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("c[%d][%d] = %d\n", i, j, c[i][j]);
}
}
free(a);
free(b);
free(c);
return 0;
}
From the updated requirement, the actual function prototype is int *multiply(int *a, int *b, int n); so the code should use a "flattened" matrix representation consisting of a 1-D array of length n * n.
Using a flattened representation, element (i, j) of the n * n matrix m is accessed as m[i * n + j] or equivalently using the unary * operator as *(m + i * n + j). (I think the array indexing operators are more readable.)
First, let us fix some errors in the for loop variables. In multiply:
for (int k = 0; i < n; k++) {
should be:
for (int k = 0; k < n; k++) {
In main:
for (int j = 0; i < 2; j++) {
should be:
for (int j = 0; j < 2; j++) {
The original code has a loop that sums the terms for each element of the resulting matrix c, but is missing the initialization of the element to 0 before the summation.
Corrected code, using the updated prototype with flattened matrix representation:
#include <stdio.h>
#include <stdlib.h>
int* multiply(int* a, int* b, int n) {
int *c = malloc(sizeof(int) * n * n);
// Rows of c
for (int i = 0; i < n; i++) {
// Columns of c
for (int j = 0; j < n; j++) {
// c[i][j] = Row of a * Column of b
c[i * n + j] = 0;
for (int k = 0; k < n; k++) {
c[i * n + j] += a[i * n + k] * b[k * n + j];
}
}
}
return c;
}
int main() {
int *a = malloc(sizeof(int) * 2 * 2);
int *b = malloc(sizeof(int) * 2 * 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
a[i * 2 + j] = i - j;
b[i * 2 + j] = j - i;
}
}
int *c = multiply(a, b, 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("c[%d][%d] = %d\n", i, j, c[i * 2 + j]);
}
}
free(a);
free(b);
free(c);
return 0;
}
You need to fix multiple errors here:
1/ line 5/24/28: int **c = malloc(sizeof(int*) * n )
2/ line 15: k<n
3/ Remark: use a[i][j] instead of *(*(a+i)+j)
4/ line 34: j<2
5/ check how to create a 2d matrix using pointers.
#include <stdio.h>
#include <stdlib.h>
int** multiply(int** a, int** b, int n) {
int **c = malloc(sizeof(int*) * n );
for (int i=0;i<n;i++){
c[i]=malloc(sizeof(int) * n );
}
// Rows of c
for (int i = 0; i < n; i++) {
// Columns of c
for (int j = 0; j < n; j++) {
// c[i][j] = Row of a * Column of b
for (int k = 0; k < n; k++) {
c[i][j] += a[i][k] * b[k][j];
}
}
}
return c;
}
int main() {
int **a = malloc(sizeof(int*) * 2);
for (int i=0;i<2;i++){
a[i]=malloc(sizeof(int)*2);
}
int **b = malloc(sizeof(int) * 2);
for (int i=0;i<2;i++){
b[i]=malloc(sizeof(int)*2);
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
a[i][j] = i - j;
b[i][j] = i - j;
}
}
int **c = multiply(a, b, 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("c[%d][%d] = %d\n", i, j, c[i][j]);
}
}
free(a);
free(b);
free(c);
return 0;
}
I'm trying to solve Gaussian Elimination and Back Substitution in C.
But I've got Segmentation fault(Core dumped) error in shell.
this is the part of main code.
float **a = (float **) malloc(sizeof(float*) *n);
for (int i = 0; i < n; i++)
a[i] = (float*) malloc(sizeof(float) *n);
float *b = (float*) malloc(sizeof(float) *n);
float *x = (float*) malloc(sizeof(float) *n);
Gaussian(n, &a, &b);
BackSubstitution(n, &a, &b, &x);
and below is gaussian.c . I think there is some problem with gaussian.c
#include <math.h>
void Gaussian(int n, float ***arr, float **arr2)
{
for (int l = 0; l < n - 1; l++)
{
for (int i = l + 1, j = 1; i < n && j < n; i++, j++)
{ (*arr)[i][j] = (*arr)[i][j] - ((*arr)[i][l] / (*arr)[l][l]) * (*arr)[l][j];
(*arr2)[i] = (*arr2)[i] - ((*arr)[i][l] / (*arr)[l][l]) * (*arr2)[l];
}
}
}
void BackSubstitution(int n, float ***arr, float **arr2, float **result)
{
for (int i = n - 1; i > 0; i--)
{
(*result)[i] = (*arr2)[i] / (*arr)[i][i];
for (int j = 0; j < i; j++)
{ (*arr2)[j] = (*arr2)[j] - (*result)[i] * (*arr)[j][i];
(*arr)[j][i] = 0;
}
}
}
Is there something wrong that generate segmentation fault?
A few things:
You have no reason to pass your arrays by pointer reference. So your functions gets much easier by eliminating one extra reference:
void Gaussian(int n, float** arr, float* arr2) {
for (int l = 0; l < n - 1; l++) {
for (int i = l + 1, j = 1; i < n && j < n; i++, j++) {
arr[i][j] = arr[i][j] - arr[i][l] / arr[l][l] * arr[l][j];
arr2[i] = arr2[i] - arr[i][l] / arr[l][l] * arr2[l];
}
}
}
void BackSubstitution(int n, float** arr, float* arr2, float* result) {
for (int i = n - 1; i > 0; i--) {
result[i] = arr2[i] / arr[i][i];
for (int j = 0; j < i; j++) {
arr2[j] = arr2[j] - result[i] * arr[j][i];
arr[j][i] = 0;
}
}
}
Second, you aren't actually initializing the contents of your arrays with valid data. Some of your array initializations are missing initializations to actual floating point data. Without this, your arrays have garbage data - which won't play well with floating point.
So aside from initializing your arrays correctly, you don't have to pass them in by pointer (because arrays degrade to pointers in function calls)
int n = 10;
float** a = (float**)malloc(n * sizeof(float*));
for (int i = 0; i < n; i++)
{
a[i] = (float*)malloc(n * sizeof(float));
for (int j = 0; j < n; j++)
{
a[i][j] = 0.0f; // you initialize a[i][j] with your data
}
}
float* b = (float*)malloc(n * sizeof(float));
float* x = (float*)malloc(n * sizeof(float));
for (int i = 0; i < n; i++)
{
b[i] = 0.0f;
x[i] = 0.0f;
}
Gaussian(n, a, b);
BackSubstitution(n, a, b, x);
I am writing a blocked matrix multiplication algorithm for n x n matrices. My matrices are stored as 1D arrays. My first version of the algorithm works fine:
double * blocked_ijk_matmul(double *A, double *B, int n, int b) {
double *C = (double *) malloc(n * n * sizeof(double));
int i_block, j_block, k_block, i, j, k;
for (i_block = 0; i_block < n; i_block += b) {
for (j_block = 0; j_block < n; j_block += b) {
for (k_block = 0; k_block < n; k_block += b) {
for (i = i_block; i < fmin(i_block + b, n); ++i) {
for (j = j_block; j < fmin(j_block + b, n); ++j) {
for (k = k_block; k < fmin(k_block + b, n); ++k) {
C[(i * n) + j] += A[(i * n) + k] * B[(k * n) + j];
}
}
}
}
}
}
return C;
}
However, in this algorithm C[(i *n) * j] is computed quite a large number of times depending on the size of the matrices. If I instead try to store this sum, and then set the value of C[(i *n) * j] to the total sum value when all summations are complete, I get incorrect results:
double * blocked_ijk_matmul(double *A, double *B, int n, int b) {
double *C = (double *) malloc(n * n * sizeof(double));
int i_block, j_block, k_block, i, j, k;
for (i_block = 0; i_block < n; i_block += b) {
for (j_block = 0; j_block < n; j_block += b) {
for (k_block = 0; k_block < n; k_block += b) {
for (i = i_block; i < fmin(i_block + b, n); ++i) {
for (j = j_block; j < fmin(j_block + b, n); ++j) {
double sum = 0;
for (k = k_block; k < fmin(k_block + b, n); ++k) {
sum += A[(i * n) + k] * B[(k * n) + j];
}
C[(i * n) + j] = sum;
}
}
}
}
}
return C;
}
I cannot figure out for quite some time why this is not working. Clearly, double sum = 0; and C[(i * n) + j] = sum; need to be placed somewhere else, but I cannot figure out where.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#define M 5
#define N 3
double **create_matrix(int m, int n);
void destroy_matrix(double **matrix, int m);
int main(void)
{
int i = 0, j = 0;
int x = 0;
double **matrix;
matrix = create_matrix(M, N);
while (i < M) {
j = 0;
while (j < N) {
printf("%4.0f", *(*(matrix + j) + i) = j);
j++;
}
putchar('\n');
i++;
}
destroy_matrix(matrix, M);
return 0;
}
double **create_matrix(int m, int n)
{
int i = 0;
double **matrix;
if ((matrix = (double **) malloc(sizeof(double *) * m)) != NULL) {
while (i < m)
if ((*(matrix + i++) = (double *) malloc(sizeof(double) * n)) == NULL)
return NULL;
return matrix;
} else
return NULL;
}
void destroy_matrix(double **matrix, int m)
{
int i = 0;
while (i < m)
free((void *) *(matrix + i++));
free((void *) matrix);
}
Allocating, initializing and printing the matrix works.
Allocating, not initializing and freeing works.
Allocating, initializing AND freeing does NOT work.
Backtrace:
*** glibc detected *** [file]: free(): invalid next size (fast): 0x0000000001e7d040 ***
Followed by a memory map.
I searched for similar problems but couldn't find one fitting my situation, nor could I derive mine from them.
Your matrix allocation and deallocation functions look fine to me.
But the initialization of the matrix elements has an error:
while (i < M) {
j = 0;
while (j < N) {
printf("%4.0f", *(*(matrix + j) + i) = j);
j++;
}
putchar('\n');
i++;
}
This expression
*(*(matrix + j) + i)
has to be changed by this expression
*(*(matrix + i) + j)
because i are your rows and j are your columns.
Note that you could also use the simpler form matrix[i][j] which is equivalent to *(*(matrix + i) + j) in your program.
You are freeing the dereference, i.e. the address pointed to by the contents of the array. Try this instead. Note the lack of '*' before '(matrix + i++) on line 6
void destroy_matrix(double **matrix, int m)
{
int i = 0;
while (i < m)
free((void *) (matrix + i++));
free((void *) matrix);
}