I have the following warnings during the compilation:
solver.c:24: warning: passing argument 2 of ‘mtrx_multiple’ from incompatible pointer type
mat.h:5: note: expected ‘double *’ but argument is of type ‘double **’
solver.c:30: warning: assignment makes pointer from integer without a cast
solver.c:39: warning: assignment makes pointer from integer without a cast
/tmp/ccmU9zRf.o: In function `vec_norm':
math.c:(.text+0x331): undefined reference to `sqrt'
collect2: ld returned 1 exit status
the lines are:
solver.c
double *cg_solve( sparse_mat_t A, double *b, double *x ) {
double *a;
double **r;
double *be;
double **p;
double **x0;
x0[0] = vec_copy(x, size);
...
line 24: r[0] = vec_subtraction( b, mtrx_multiple(A, x0), size );
line 30: x0[k+1] = vec_addition( x0[k], vec_numb_multiple(a[k], p[k], size), size );
line 39: p[k+1] = vec_addition( r[k+1], vec_numb_multiple(be[k], p[k], size), size );
}
math.h
line 5: double *mtrx_multiple (sparse_mat_t A, double *c);
The function that are used there: (math.c)
double *vec_subtraction (double *a, double *b, int n) {
double *result = malloc(sizeof(double)*n);
int i;
for(i=0; i<n; i++)
result[i] = a[i]-b[i];
return result;
}
double *vec_addition (double *a, double *b, int n) {
double *result = malloc(sizeof(double)*n);
int i;
for(i=0; i<n; i++)
result[i] = a[i]+b[i];
return result;
}
double *vec_numb_multiple (double a, double *b, int n) {
double *result = malloc(sizeof(double)*n);
int i;
for(i=0; i<n; i++)
result[i] = a*b[i];
return result;
}
double *mtrx_multiple (sparse_mat_t A, double *c) {
double *result;
int i, j;
result = malloc((A.size) * sizeof *result);
printf("c.n: %d \n", A.size);
for (i = 0; i < A.size; i++) {
int v = 0;
for (j = A.ia[i]; j < A.ia[i + 1]; j++) {
v += A.a[j] * c[A.ja[j]];
}
result[i] = v;
}
return result;
}
double vec_norm (double *a, int n){
double result;
int i;
for(i=0; i<n; i++)
result = result + ( a[i] * a[i] );
result = sqrt(result);
return result;
}
double *vec_copy (double *a, int n) {
double *result;
int i;
for(i=0; i<n; i++)
result[i] = a[i];
return result;
}
I will be grateful for any help.
EDIT
I found the solution to the x0 problem, thanks Ben. Now what left is:
solver.c:30: warning: assignment makes pointer from integer without a cast
solver.c:39: warning: assignment makes pointer from integer without a cast
/tmp/ccL4uSoH.o: In function 'vec_norm':
math.c:(.text+0x331): undefined reference to 'sqrt'
collect2: ld returned 1 exit status
Based on what you've posted, I'm going to guess that you don't have a declaration for vec_numb_multiple in scope before you call it, and the compiler is implicitly typing it to return int; that would lead to the warnings on lines 30 and 39.
The undefined reference to sqrt() means you aren't linking in the standard math library; I'm assuming you're using gcc, so you would need to add -lm to the command line.
It's a really bad idea to use a standard library file name for your own code (math.h, math.c).
replace (line 24)
r[0] = vec_subtraction( b, mtrx_multiple(A, x0), size );
with
r[0] = vec_subtraction( b, mtrx_multiple(A, x0[0]), size );
You said you whant to multiply a matrix (A I guess) with a vector, so the second argument must be a vector. x0 is a pointer to pointers which can be see as a 2D array of doubles, it means a single cell of x0 is an array of doubles (ie. what you could call a vector). This is why you want to pass x0[0], not just x0 which is : many arrays.
see John's aswer for the rest.
Related
This question already has answers here:
How to pass a 2D array by pointer in C?
(5 answers)
Closed 4 months ago.
#include <stdio.h>
void triU(double **U, double *b, int n)
{
n--;
b[n] /= U[n][n];
for(int i = n - 1; i >= 0; i--)
{
double aux_sum = 0;
for(int j = i + 1; j <= n; j++)
aux_sum += (U[i][j] * b[j]);
b[i] = (b[i] - aux_sum) / U[i][i];
}
}
int main()
{
int n = 3;
double U[][n] = {{5, -5, 10}, {0, 2, 4}, {0, 0, -1}};
double b[] = {25, 16, -2};
triU(U, b, n);
for(int i = 0; i < n; i++)
printf("%le \n", b[i]);
return 0;
}
This is the code for what I am trying to do. I am supposed to make a method with the parameters written in that way to pass the two matrices.
However I keep getting the following error.
triU.c: In function ‘int main()’:
triU.c:21:10: error: cannot convert ‘double (*)[n]’ to ‘double**’
21 | triU(U, b, n);
| ^
| |
| double (*)[n]
triU.c:3:20: note: initializing argument 1 of ‘void triU(double**, double*, int)’
3 | void triU(double **U, double *b, int n)
| ~~~~~~~~~^
I would appreciate any help on how I am supposed to pass arrays by pointers in C.
Thank you very much.
In this call of the function triU:
triU(U, b, n);
the two-dimensional array U is implicitly converted to pointer to its first element of the type double ( * )[3]. But the corresponding function parameter has the type double ** and there is no implicit conversion between the pointer types. So the compiler issues a message.
If your compiler supports variable length arrays (and your compiler support VLAs) then declare the function like:
void triU( size_t n, double ( *U )[n], double *b );
or:
void triU( size_t n, double U[][n], double *b );
and call it like:
triU( n, U, b );
Otherwise declare the function like:
void triU( double ( *U )[3], double *b, size_t n );
or:
void triU( double U[][3], double *b, size_t n );
and call it like:
triU( U, b, n );
Pay attention to that this for loop:
for(int j = i + 1; j <= n; j++)
aux_sum += (U[i][j] * b[j]);
can invoke undefined behavior when j is equal to n because the valid range of indices is [0, n).
Also bear in mind that the length modifier in the format string in this call:
printf("%le \n", b[i]);
is redundant and has no effect. You may write:
printf("%e \n", b[i]);
I'm trying to change a value of an element of a complex matrix in c.
After trying to do, the printed result of the element is 0, any idea on how to fix this?
Here is my code, thanks in advance.
int main()
{
int size = 2;
double _Complex **x;
double _Complex v;
//Creating complex matrix
x = (double _Complex **)malloc( size* sizeof(double _Complex *) );
x[0] = (double _Complex *)malloc( (int)(size*size)* sizeof(double _Complex ));
for(int i = 1; i < size; i++ )
x[i] = x[0] + (unsigned long)size * i;
//Printing the matrix
printf("Before \n");
for (int h = 0; h < size; h++)
{
for (int w = 0; w < size; w++)
{
v = x[h][w];
printf( "%d + i* %d ,", creal(v), cimag(v));
}
printf("\n");
}
//Changing the value
int _Complex t = 1 + 5*_Complex_I;
x[0][0] = t;
//Print the matrix after the change
return 0;
}
After trying to do, the printed result of the element is 0, any idea on how to fix this?
Wrong format specifier
double _Complex v;
...
// printf("%d + i* %d ,", creal(v), cimag(v));
printf("%g + i* %g ,", creal(v), cimag(v));
Save time, enable all compiler warnings.
warning: format '%d' expects argument of type 'int', but argument 3 has type 'double' [-Wformat=]
Complex int types
Such types int _Complex may cause warning: ISO C does not support complex integer types [-Wpedantic]. Recommend double _Complex.
// int _Complex t = 1 + 5*_Complex_I;
double _Complex t = 1 + 5*_Complex_I;
Uninitialized data
When printing, the complex values have not been assigned. Perhaps zero them with calloc(). Cast not needed in C. Perform multiplication using size_t math. Better to take the size of the de-reference pointer, than the type - easier to code right, review and maintain.
// x[0] = (double _Complex *)malloc( (int)(size*size)* sizeof(double _Complex ));
x[0] = calloc( (size_t) size * size, sizeof x[0][0]);
I have the following functions:
int sum(int *a, int size) {
int sum;
int i;
for(i = 0; i < size; i++) {
sum += a[i];
}
return sum; /* Change the return value */
}
and
double average(int *a, int size) {
int summation = sum(*a, size);
double result = (double) summation/size;
return result; /* Change the return value */
}
and when I compile, I get the error: passing argument makes pointer from integer without a cast
What should I change?
In your average function, don't pass *a to sum, but just a since it's already a pointer.
Since a is an array, just passing a will give the base address of the array, so just pass a in the argument.
I have the following code shown below
To call the function the code looks similar to the following:
#define N 2
static float m1[N][N] = {{1.0, -0.02}, {0.0, 1.0}};
static float m2[N][1] = {{1.5f}, {1.5f}};
static float result[N][1];
int main(void)
{
matrix_multiply((float*) m1, (float*) m2, N, N, 1, (float*) result);
}
void matrix_multiply(float* input_matrix1, float* input_matrix2, int m, int p, int n, float* output_matrix)
{
// Matrix Multiplication Routine
// input_matrix1= input matrix (m x p)
// input_matrix2 = input matrix (p x n)
// m = number of rows in input_matrix1
// p = number of columns in input_matrix1 which should equal the number of rows in input_matrix2
// n = number of columns in input_matrix2
// output_matrix = output matrix = input_matrix1*input_matrix2 (m x n)
//.....Code that does matrix multiplication
}
I haven't come across the (float*) being used when calling a function. Can someone describe it in detail.
The notation (float *)X is a cast. The cast is necessary if the matrix multiply function is declared (or defined) before it is used, as it should be, because the types being passed to the function are not float * as the function expects but float (*)[2] (which is a pointer to an array). The casts tell the compiler 'we know more about this C than you do', even though that is a very debatable proposition.
Here is a mildly modified version of the code in the question:
#define N 2
static float m1[N][N] = {{1.0, -0.02}, {0.0, 1.0}};
static float m2[N][1] = {{1.5f}, {1.5f}};
static float result[1][N];
void matrix_multiply(float *input_matrix1, float *input_matrix2, int m, int p, int n, float *output_matrix);
int main(void)
{
matrix_multiply( m1, m2, N, N, 1, result);
matrix_multiply(&m1[0][0], &m2[0][0], N, N, 1, &result[0][0]);
matrix_multiply((float*) m1, (float*) m2, N, N, 1, (float*) result);
}
void matrix_multiply(float *input_matrix1, float *input_matrix2, int m, int p, int n, float *output_matrix)
{
// Matrix Multiplication Routine
// input_matrix1 = input matrix (m x p)
// input_matrix2 = input matrix (p x n)
// m = number of rows in input_matrix1
// p = number of columns in input_matrix1 and the number of rows in input_matrix2
// n = number of columns in input_matrix2
// output_matrix = output matrix = input_matrix1*input_matrix2 (m x n)
//.....Code that does matrix multiplication
}
When compiled with GCC 4.7.1 on Mac OS X 10.8.4, the output is:
$ gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -c matmul89.c
matmul89.c: In function ‘main’:
matmul89.c:10:5: warning: passing argument 1 of ‘matrix_multiply’ from incompatible pointer type [enabled by default]
matmul89.c:6:6: note: expected ‘float *’ but argument is of type ‘float (*)[2]’
matmul89.c:10:5: warning: passing argument 2 of ‘matrix_multiply’ from incompatible pointer type [enabled by default]
matmul89.c:6:6: note: expected ‘float *’ but argument is of type ‘float (*)[1]’
matmul89.c:10:5: warning: passing argument 6 of ‘matrix_multiply’ from incompatible pointer type [enabled by default]
matmul89.c:6:6: note: expected ‘float *’ but argument is of type ‘float (*)[2]’
matmul89.c: In function ‘matrix_multiply’:
matmul89.c:17:29: warning: unused parameter ‘input_matrix1’ [-Wunused-parameter]
matmul89.c:17:51: warning: unused parameter ‘input_matrix2’ [-Wunused-parameter]
matmul89.c:17:70: warning: unused parameter ‘m’ [-Wunused-parameter]
matmul89.c:17:77: warning: unused parameter ‘p’ [-Wunused-parameter]
matmul89.c:17:84: warning: unused parameter ‘n’ [-Wunused-parameter]
matmul89.c:17:94: warning: unused parameter ‘output_matrix’ [-Wunused-parameter]
$
The unused parameter warnings are reasonable; the function is still a dummy with no code. Line 10 is the call to matrix_multiply() without the casts. As you can see, GCC diagnoses that the types of the matrix arguments are not float * but are pointers arrays. The second call is the way I'd write it, avoiding any need for casts. The third call bludgeons the compiler into accepting the code with the casts, and it will in fact work correctly, but there is really no need to do the bludgeoning.
Working C99 code
If you've got C99 available, you can make use of VLAs — variable length arrays — to write the code neatly:
#include <stdio.h>
#define N 2
static float m1[N][N] = {{1.0, -0.02}, {0.0, 1.0}};
static float m2[N][1] = {{1.5f}, {1.5f}};
static float result[1][N];
void matrix_multiply(int m, int p, int n, float matrix1[m][p], float matrix2[p][n], float output[m][n]);
void matrix_print(const char *tag, int m, int n, float matrix[m][n]);
int main(void)
{
matrix_multiply(N, N, 1, m1, m2, result);
matrix_print("m1", N, N, m1);
matrix_print("m2", N, 1, m2);
matrix_print("m3", 1, N, result);
}
void matrix_multiply(int m, int p, int n, float matrix1[m][p], float matrix2[p][n], float output[m][n])
{
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
output[i][j] = 0.0;
for (int i = 0; i < m; i++)
for (int j = 0; j < p; j++)
for (int k = 0; k < n; k++)
output[i][k] += matrix1[i][j] * matrix2[j][k];
}
void matrix_print(const char *tag, int m, int n, float matrix[m][n])
{
printf("%s (%d x %d):\n", tag, m, n);
for (int i = 0; i < m; i++)
{
char *pad = "[";
for (int j = 0; j < n; j++)
{
printf("%s%6.3f", pad, matrix[i][j]);
pad = ", ";
}
printf("%s", " ]\n");
}
}
This compiles without warnings and produces the plausible-looking output:
m1 (2 x 2):
[ 1.000, -0.020 ]
[ 0.000, 1.000 ]
m2 (2 x 1):
[ 1.500 ]
[ 1.500 ]
m3 (1 x 2):
[ 1.470, 1.500 ]
Writing the code to simulate the address arithmetic using C89 is fiddly — far from impossible, but fiddly.
Working C89 code
#include <stdio.h>
#define N 2
static float m1[N][N] = {{1.0, -0.02}, {0.0, 1.0}};
static float m2[N][1] = {{1.5f}, {1.5f}};
static float result[1][N];
void matrix_multiply(float *matrix1, float *matrix2, int m, int p, int n, float *output);
void matrix_print(const char *tag, int m, int n, float *matrix);
int main(void)
{
matrix_multiply(&m1[0][0], &m2[0][0], N, N, 1, &result[0][0]);
matrix_print("m1", N, N, &m1[0][0]);
matrix_print("m2", N, 1, &m2[0][0]);
matrix_print("m3", 1, N, &result[0][0]);
return 0;
}
/*
** Matrix Multiplication Routine
** matrix1 = input matrix (m x p)
** matrix2 = input matrix (p x n)
** m = number of rows in matrix1
** p = number of columns in matrix1 and number of rows in matrix2
** n = number of columns in matrix2
** output = output matrix = matrix1 * matrix2 (m x n)
*/
void matrix_multiply(float *matrix1, float *matrix2, int m, int p, int n, float *output)
{
int i, j, k;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
output[i*n+j] = 0.0;
for (i = 0; i < m; i++)
for (j = 0; j < p; j++)
for (k = 0; k < n; k++)
output[i*n+k] += matrix1[i*p+j] * matrix2[j*n+k];
}
void matrix_print(const char *tag, int m, int n, float *matrix)
{
int i, j;
printf("%s (%d x %d):\n", tag, m, n);
for (i = 0; i < m; i++)
{
char *pad = "[";
for (j = 0; j < n; j++)
{
printf("%s%6.3f", pad, matrix[i*n+j]);
pad = ", ";
}
printf("%s", " ]\n");
}
}
The output for the C89 and C99 code is the same.
I have some trouble when compiling this
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <time.h>
int perkalianMatriks(double ** A, double ** B, double ** C, int n);
int randomMatriks(double * m, int n);
int main(int argc, char *argv[]) {
int n_order = 0 , i, j;
double ** A, ** B, ** C;
time_t time1, time2;
double diff_sec;
randomMatriks(double * m, int n)
A = (double **) malloc(sizeof(double) * n_order);
B = (double **) malloc(sizeof(double) * n_order);
C = (double **) malloc(sizeof(double) * n_order);
for (i = 0; i < n_order; i++) {
A[i] = (double *) calloc(sizeof(double), n_order);
B[i] = (double *) calloc(sizeof(double), n_order);
C[i] = (double *) calloc(sizeof(double), n_order);
}
printf("\nMatrix Sizes : ");
scanf("%d", %n_order);
time(&time1);
perkalianMatriks(A, B, C, n_order);
time(&time2);
diff_sec = difftime (time2,time2);
printf ("Total time to execute %f seconds.\n", diff_sec);
return 0;
}
int randomMatriks(double * m, int n) {
int i;
for (i = 0; i < n_order; i++) {
m[i] = (double) (rand() % 10) + 1;
}
}
int perkalianMatriks(double ** a, double ** b, double ** c, int n) {
int i, j, k;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
c[i][j]=0;
for (k = 0; k < n; k++)
{
c[i][j] += a[i][k] * b[k][j];
}
}
}
return 0;
}
Error when compiling
sekuensial.c(16): error C2143: syntax error : missing ')' before
'type'
sekuensial.c(16): error C2198: 'randomMatriks' : too few arguments
for call
sekuensial.c(16): error C2059: syntax error : ')'
sekuensial.c(29): error C2059: syntax error : '%'
sekuensial.c(45): error C2065: 'n_order' : undeclared identifier
Does anyone can help me fix this?
You're missing a semi-colon. And you can't name a variable double. I guess this line should just be removed, since it is a cut and paste of the declaration above. If you need to call it, you should call it with real arguments. I don't see that you defined anything suitable for the first parameter, I guess from later on in your code, you intend to use n_order for the second parameter.
randomMatriks(double * m, int n)
^^^^^^ ^^^
This scanf is wrong, you probably want &:
scanf("%d", %n_order);
^^^
The variable dif_sec doesn't exist. Typo.
dif_sec = difftime (time2,time2);
^^^^^^^
printf ("Total time to execute %f seconds.\n", dif_sec);
^^^^^^^
The variable n_order doesn't exist. n instead probably.
for (i = 0; i < n_order; i++) {
^^^^^^^
The randomMatriks should return something. It falls off without a return statement, even though it is declared to return an int.
You have some unused variables and function parameters.
int main(int argc, char *argv[]) {
^^^^ ^^^^
int n_order = 0 , i, j;
^^^
The problem is that you never initialized your C array, which is an array of pointers to pointers to double. In perkalianMatriks, it's deferenced, and at that point, all bets are off as to what the pointer is (0xfdfdfdfd in your case).
(I'm guessing you might not understand what a ** type really is and how it's supposed to be used?)
That is not correct way of allocating memory for *B and so on.
See example on allocating memory for double pointers (*B) and so for the rest of pointers.
Also take care of semi colons.
It is quite simple to perform multiplication of two matrices.
Your can get a simple clue at : solvedc.com