I am trying to multiply a 1D matrix as a 2D matrix in C.
Here is one example of what result I get with a 2D loop:
(the + should be a * I miss typed)
So I get a matrix C with the values
{
{2,3},
{6,11}
};
Here is the code for the 2D array in C:
void multiply(int n, double ** a, double ** b, double ** c) {
int i, j, k;
for (i = 1; i < n; i++){
for (j = 1; j < n; j++){
for (k = 1; k < n; k++){
c[i][j] += a[i][k] * b[k][j];
}
}
}
}
Now, I am trying to do the same, but for a 1D matrix, like in the picture:
(the + should be a * I miss typed)
And here is the code for the 1D array:
void multiply(int n, double * a, double * b, double * c) {
int i, j, k;
for (i = 0; i < n*n; i++) {
for (j = 0; j < n*n; j++) {
for (k = 0; k < n*n; k++) {
c[i]+= a[j]*b[k];
}
}
}
}
After running it, I get the result {14400, 14400,14400,14400} instead of {2,3,6,11}
It looks like you just want to do matrix multiplication while working with one-D arrays instead of 2-d. Not sure why you'd want to do that but you could do something like this:
void multiply(int n, double *a, double *b, double *c) {
int i, j, k;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
for (k = 0; k < n; k++) {
c[i * n + j] += a[i * n + k] * b[k * n + j];
}
}
}
}
Related
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 trying to raise a matrix to a power, using pointers but there is a mistake in my code I can't find.
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
>
int **alloc(int r, int c) {
int **d;
d = (int **)malloc(r * sizeof(int *));
for (int i = 0; i < r; i++) {
d[i] = (int *)malloc(c * sizeof(int));
}
return d;
void input(int **A, int r, int c) {
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
printf("[%d][%d]=", i, j);
scanf_s("%d", &A[i][j]);
}
}
}
void output(int **A, int r, int c) {
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
printf("%d ", A[i][j]);
}
printf("\n");
}
}
void power(int **A,int**D, int r, int c,int p) {
int i, j,k;
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
D[i][j] = A[i][j];
}
}
while (p) {
// this is the matrix multiplication, where I attempt to multiply my matrix A with itself, and store the result in D, which initially started as A's copy, and p is the power I'm raising it to.
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
for (k = 0; k < c; k++)
D[i][j] = D[i][j] + A[i][k] * D[k][j];
}
}
p--;
}
}
void main() {
int r, c;
int **A, **D;
printf("rows A: ");
scanf_s("%d", &r);
printf("columns A: ");
scanf_s("%d", &c);
A = alloc(r, c);
printf("\nValues of A:\n");
input(A, r, c);
printf("\nMatrIX A is:\n");
output(A, r, c);
D = alloc(r, c);
printf("input the value you want to raise your matrix to: ");
int p;
scanf_s("%d", &p);
power(A, D, r, c, p);
printf("\nMatrix raised to said power is:\n");
output(D, r, c);
_getch();
}
When I input the rows and columns as 2 each, and input all values in the matrix as 1 and raise it to the power of 3, my answer should be
4 4
4 4
instead of
72 72
232 232
What is wrong in my code? If I were to print the D matrix before the multiplication, it would print it correctly, as:
1 1
1 1
Your two-step allocation looks okay, except that you don't free the memory after you're done. Your problem is in how you multiply the matrix:
Raising a matrix to a power involves multiplying it to itself. You can only do that if the matrix is square. You can replace all occurrences of rows r and columns c with a single dimension n.
When you do the actual multiplication:
D[i][j] = D[i][j] + A[i][k] * D[k][j];
you assign to D and read from it at the same time. Subsequent calculations (of the same multiplication) will see a changed value of D[i][j]. You will need a temporary "scratch" matrix.
Your code multiplies once too many. Also, Raising a matrix to the power of zero should yield the identity matrix.
Here's how your power function could look like:
void power(int **A, int **D, int n, int p)
{
int i, j,k;
// assign identity matrix to result D
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
D[i][j] = (i == j);
}
}
// create a scratch matrix
int **tmp = alloc(n);
while (p-- > 0) {
// multiply [tmp] = [A] * [D]
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
tmp[i][j] = 0;
for (k = 0; k < n; k++)
tmp[i][j] += A[i][k] * D[k][j];
}
}
// copy [D] = [tmp]
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
D[i][j] = tmp[i][j];
}
}
}
// TODO: clean up the scratch matrix
}
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.
I'm trying to transpose a matrix in C while passing the matrix to a function and return a pointer to a transposed matrix. What am I doing wrong in the second while loop?
in main
ptr = (float *) getMatrix(numRowsB, numColsB);
transposePtr = transpose(ptr, numRowsB, numColsB);
printf("\nBtranspose =\n");
printMatrix(transposePtr, numColsB, numRowsB);
create matrix
float* getMatrix(int n, int m)
{
int i, j;
float *arrayPtr;
if ((n <= 0) || (m <= 0))
{
printf("function getMatrix(): matrix dimensions are invalid\n");
return NULL;
}
arrayPtr = (float *) malloc(n*m*sizeof(float));
if(arrayPtr == NULL)
{
printf("function getMatrix: Unable to malloc array\n");
return NULL;
}
transpose function
float* transpose(float *matrix, int n, int m)
{
int i = 0;
int j = 0;
float num;
float *transposed=(int*) malloc(sizeof(int)*n*m);
while(i < n-1)
{
while(j < m-1)
{
num = *(matrix+i*m+j);
*(transposed+j*m+i)= num;
j++;
}
i++;
}
return transposed;
}
print fucntion
void print(float *matrix, int n, int m)
{
int i = 0;//row counter
int j = 0;//col counter
for(i = 0; i < n; i++){
printf("\n");
for(j = 0; j < m; j++){
printf("%f ", *(matrix + i*n + j));
}
}
}
Example input:
1 2 3
4 5 6
Output:
1.000000 0.000000
2.000000 3396.580087
-0.000000 0.000000
Part of the problem was your print function
Here is a version of your functions that works:
float* transpose(float *matrix, int n, int m)
{
int i = 0;
int j = 0;
float num;
float *transposed=malloc(sizeof(float)*n*m);
while(i < n) {
j = 0;
while(j < m) {
num = *(matrix + i*m + j);
*(transposed + i+n*j) = num; // I changed how you index the transpose
j++;
}
i++;
}
return transposed;
}
void print(float *matrix, int n, int m)
{
int i = 0;//row counter
int j = 0;//col counter
for(i = 0; i < n; i++){
printf("\n");
for(j = 0; j < m; j++){
printf("%f ", *(matrix + i*m + j)); // Changed from n to m
}
}
}
There were a few things.
Use sizeof(float) instead of sizeof(int)
Your loop should be i < n and j < m instead of i < n-1 and j < m-1 and finally you need to reset j to zero every time
The matrix indexes in inner most loop of your transpose function was incorrect
Your print function was using the wrong variable in the multiplication
Also it is generally considered bad practice to cast the result of malloc in C.