matrix multiplication can't be compile - c

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

Related

Trying to pass 2d array to function in C [duplicate]

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]);

Is it OK to pass (double ***) pointers using (void **)?

I compile the code below with gcc using -Wall -Werror and it compiles cleanly, runs as expected; however, I'm just curious if it is OK, in ANSI and/or ISO C context, to pass a (double ***) pointer via (void **).
The ISO/IEC 9899:2017, section 6.6 - 9 says:
"The array-subscript [] and member-access . and -> operators,
the address & and indirection * unary operators, and pointer
casts may be used in the creation of an address constant, but the
value of an object shall not be accessed by use of these operators."
In connection to this recommendation, the function allocateMatrix is, in fact, supposed to just allocate memory and return the corresponding address; so, please disregard the inner loop that assign values, it's there for test purposes only.
void allocateMatrix(int n, void **a) {
int i = 0, j = 0;
double **pTmp = calloc(n, sizeof(double *));
for (i = 0; i < n; i++) {
pTmp[i] = malloc(n * sizeof(double));
// following loop is inserted to make sure code runs as expected
// this does not exists in real code
for (j = 0; j < n; j++) {
pTmp[i][j] = (double)(i + 1) + (double)(j + 1) / 10.0f;
}
}
*a = pTmp;
return;
}
int main(int argc, char const *argv[]) {
int i = 0, j = 0;
int n = 5;
double **a = NULL;
// "a" is a (double **) pointer; so, "&a" is now a (double ***) pointer
allocateMatrix(n, (void **)&a);
// testing...
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%6.2lf", a[i][j]);
}
printf("\n");
}
return 0;
}
The C standard allows for conversion to and from void *, however that lattitute does not exist for void **.
Change the function argument to void * and cast it appropriately and it will work.
void allocateMatrix(int n, void *a) {
...
*(double ***)a = pTmp;
}
And change remove the cast from the function call:
allocateMatrix(n, &a);

segfault error: struct, pointer, 2D array

I am playing around with pointers and structs. This is the program I have been messing with. I am getting a segfault error and I am not sure why. I have looked through it for awhile but can't seem to pinpoint the issue. Can someone explain it to me?
EDIT: in createArray I am getting a segfault at *purp[i][j] = '1';
#include <stdio.h>
#include <stdlib.h>
struct purple_struct{
int x;
int y;
char **purp;
};
void print(int x, int y){
printf("%d %d\n", x, y);
return;
}
void createArray(char*** purp, int x, int y){
int i, j;
for (i = 0; i < x; ++i){
for (j = 0; j < y; ++j){
*purp[i][j] = '1';
}
}
return;
}
int main(){
int i, j;
struct purple_struct dog;
dog.x = 3;
dog.y = 4;
dog.purp = (char **)malloc(dog.x * sizeof(char *));
for (i = 0; i < dog.x; ++i){
dog.purp[i] = (char *)malloc(dog.y * sizeof(char));
}
createArray(&dog.purp, dog.x, dog.y);
for (i = 0; i < dog.x; ++i){
for (j = 0; j < dog.y; ++j){
printf("%c", dog.purp[i][j]);
}
}
print(dog.x, dog.y);
return 0;
}
You need to understand the concept of operator precedence. Just like in mathematics, where an expression like 1 + 2 × 3 means 1 + (2 × 3) and not (1 + 2) × 3, programming languages have rules as to the order in which different operators in an expression are performed.
The rules for C are here: http://en.cppreference.com/w/c/language/operator_precedence
In your case, the problem is that *purp[i][j] actually means *(purp[i][j]), and not (*purp)[i][j] as you were expecting.
void createArray(char*** purp, int x, int y){
*purp[i][j] = '1';
I think they should be
void createArray(char** purp, int x, int y){
purp[i][j] = '1';
And in main
createArray(&dog.purp, dog.x, dog.y);
'&' is not needed here because you're already passing a pointer. '&' is usually used to pass the address of a variable.
Correcting these few things it compiles just fine, not sure about what you want to do.

Access violation writing location 0x011CF000

I'm trying to get monochrome image from .bmp image with using bitmap_image.hpp library. But in one place (Pic[i][j] = 0.3 * r + 0.59 * g + 0.11 * b;) i receive that error: Unhandled exception at 0x0019BD8F in PicCircle.exe: 0xC0000005: Access violation writing location 0x011CF000. . So, that's wrong with it?
code:
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "bitmap_image.hpp"
#define C 0.01
double** ArrayCreate ( int M, int N )
{
int i;
double** ArrayRoot;
ArrayRoot = (double **)malloc(sizeof(double*) * M);
for (i = 0; i < M; i++)
ArrayRoot[i] = (double *)malloc(sizeof(double) * N);
return ArrayRoot;
}
void ArrayDestroy ( double** Array , int M)
{
int i;
for (i = 0; i < M; i++){
Array[i] = (double *)realloc(Array[i], 0);
};
Array = (double **)realloc(Array, 0);
}
void main ( void )
{
double** Pic;
unsigned char r, g, b;
int H, W, i, j;
bitmap_image image("m1.bmp");
H = image.height();
W = image.width();
Pic = ArrayCreate(H, W);
for (i = 0; i < W; i++)
for (j = 0; j < H; j++)
{
image.get_pixel(i, j, r, g, b);
Pic[i][j] = 0.3 * r + 0.59 * g + 0.11 * b;
}
for (i = 0; i < W; i++)
for (j = 0; j < H; j++)
{
if (abs(sqrt(pow(Pic[i + 1][j] - Pic[i][j], 2) + pow(Pic[i][j + 1] - Pic[i][j], 2))) >= C)
Pic[i][j] = 1;
else
Pic[i][j] = 0;
}
ArrayDestroy(Pic, H);
}
In your first loop you access the Pic array as Pic[width][height], but in the second loop you access it as Pic[height][width].
One of those two is incorrect, probably the first one.
Fixing your for loop should correct the issue.
This:
ArrayRoot = (double **)malloc(sizeof(int*) * M);
looks super-broken; it assumes sizeof (int *) to be the same as (sizeof double *) which is probably true, but still a very broken thing to write.
The follow-up is worse:
ArrayRoot[i] = (double *)malloc(sizeof(int) * N);
since sizeof (int) is very probably smaller than sizeof (double) this is going to lead to horror.
The way to avoid this category of error is to never write the type name in the malloc() argument: dereference the pointer being assigned to, instead. The latter would then become:
ArrayRoot[i] = malloc(N * sizeof *ArrayRoot[i]);
^^^^^^^^^^^^^
this part is to
the left of the =
This also drops the cast of course.

Dealing with warnings in c compilations

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.

Resources