i am very new in c programming. i am using a c code from the book 'numerical recipes in C' for polynomial regression. in this program i need to replace (*funcs) function with fpoly function.but i dont know how to do that and how to make changes in fpoly function to become like (*fpoly).could you please help me with that?
I really appreciate any help.
void fpoly(float x, float p[], int np)
//Fitting routine for a polynomial of degree np-1, with coefficients in the array p[1..np].
{
int j;
p[1]=1.0;
for (j=2;j<=np;j++) p[j]=p[j-1]*x;
}
void lfit( float x[], float y[], float sig[], int ndat, float a[], int ia[], int ma, float **covar, float *chisq, void (*funcs)(float, float [], int))
and here is the complete program:
void lfit(float x[], float y[], float sig[], int ndat, float a[], int ia[],
int ma, float **covar, float *chisq, void (*funcs) (float,float[], int))
/*Given a set of data points x[1..ndat], y[1..ndat] with individual standard deviations
sig[1..ndat], use χ2 minimization to fit for some or all of the coefficients a[1..ma] of
a function that depends linearly on a, y =sum(i)( ai × afunci(x)). The input array ia[1..ma]
indicates by nonzero entries those components of a that should be fitted for, and by zero entries
those components that should be held fixed at their input values. The program returns values
for a[1..ma], χ2 = chisq, and the covariance matrix covar[1..ma][1..ma]. (Parameters
held fixed will return zero covariances.)Th e user supplies a routine funcs(x,afunc,ma) that
returns the ma basis functions evaluated at x = x in the array afunc[1..ma].*/
{
void covsrt(float **covar, int ma, int ia[], int mfit);
void gaussj(float **a, int n, float **b, int m);
int i, j, k, l, m, mfit = 0;
float ym, wt, sum, sig2i, **beta, *afunc;
beta = matrix(1, ma, 1, 1);
afunc = vector(1, ma);
for (j = 1; j <= ma; j++)
if (ia[j])
mfit++;
if (mfit == 0)
nrerror("lfit: no parameters to be fitted");
for (j = 1; j <= mfit; j++) { //Initialize the (symmetric)mat rix.
for (k = 1; k <= mfit; k++)
covar[j][k] = 0.0;
beta[j][1] = 0.0;
}
for (i = 1; i <= ndat; i++) {
(*funcs) (x[i], afunc, ma);
ym = y[i];
if (mfit < ma) { //Subtract off dependences on known pieces
for (j = 1; j <= ma; j++) //of the fitting function.
if (!ia[j])
ym -= a[j] * afunc[j];
}
sig2i = 1.0 / SQR(sig[i]);
for (j = 0, l = 1; l <= ma; l++) {
if (ia[l]) {
wt = afunc[l] * sig2i;
for (j++, k = 0, m = 1; m <= l; m++)
if (ia[m])
covar[j][++k] += wt * afunc[m];
beta[j][1] += ym * wt;
}
}
}
for (j = 2; j <= mfit; j++) //Fill in above the diagonal from symmetry.
for (k = 1; k < j; k++)
covar[k][j] = covar[j][k];
gaussj(covar, mfit, beta, 1); //Matrix solution.
for (j = 0, l = 1; l <= ma; l++)
if (ia[l])
a[l] = beta[++j][1]; //Partition solution to appropriate coefficients
*chisq = 0.0;
for (i = 1; i <= ndat; i++) { //Evaluate χ2 of the fit.
(*funcs) (x[i], afunc, ma);
for (sum = 0.0, j = 1; j <= ma; j++)
sum += a[j] * afunc[j];
*chisq += SQR((y[i] - sum) / sig[i]);
}
covsrt(covar, ma, ia, mfit); //Sort covariance matrix to true order of fittin
free_vector(afunc, 1, ma); //coefficients.
free_matrix(beta, 1, ma, 1, 1);
}
In
void lfit( float [], float [], float [], int, float [], int [], int, float**, float*, void (*funcs)(float, float [], int))
"void (*funcs)(float, float [], int)" is the type signature of the function pointer.
If it is in-scope, you can just pass the name of your function (fpoly) in place of "void (*funcs)(float, float [], int)", without parentheses or anything. You can also take its address with the & operator but I believe it's equivalent:
lfit( all_the_other_args, ..., fpoly);
You could also have a local function pointer which holds fpoly:
void (*local_function_pointer_variable)(float, float [], int) = fpoly;
lfit( all_the_other_args, ..., local_function_pointer_variable);
In C the syntax of function pointer types is somehow inconvenient but hopefully you can define a type to hide this to some extent
typedef void (*poly_fitter)(float, float [], int);
poly_fitter function_pointer_var_of_type_poly_fitter = fpoly;
lfit( all_the_other_args, ..., function_pointer_var_of_type_poly_fitter)
If I understand correctly, you want to pass the function poly if so, then just pass the name of the function:
lfit(x, y,...., poly);
the lfit function has many input parameter.
1 of the parameter is address to a function. and that's why we have added * in the definition of that input parameter.
void (*funcs) (float, float[], int))
so when you calling lfit() function you can mention the address the address of your fpoly() function as the input of your lfit() function
the address of void fpoly(float x, float p[], int np) is fpoly or &fpoly
so when you call your function lfit() you can do it in this way:
lfit(x,y,...,fpoly)
or in this way:
lfit(x,y,...,&fpoly)
Related
I have given a two point(a[], b[]) which is d(mod) in length. I want to create a function that is able to output a point at ndistance where n is float number (1.5d,0.5d,2d). I have able to calculate the gradient and distance between a line but I dont know how to find a point along a line at nd away form the initial co-ordinate.
> #include <stdio.h>
#include <math.h>
float modulus(float vec[])
{
float mod,int i,int n;
n = 2; mod = 0.0;
for (i = 0; i < n; i++)
{
mod = mod + (vec[i] * vec[i]);
}
mod = sqrt(mod);
return mod;
}
void diff(float a[], float b[], float c[])
{
int i;
for (i = 0; i < 2; i++)
c[i] = a[i] - b[i];
}
float gradient(float a[], float b[])
{
int i;
float dx = a[0]-b[0];
float dy = a[1]-b[1];
return (dy/dx);
}
int main()
{
float a[] = {1., 1.};
float b[] = {5., 3.};
float c[2];
float len;
diff(a, b, c);
len = modulus(c);
printf("length = %.2f\n", len);
printf("\n gradient of a line : %.2f\n",gradient(a,b));
return 0;
> `Blockquote`
There are a couple of formulas that you can use for this type of linear interpolation (or extrapolation, when d > 1 or d < 0):
void lerp_2(float a[], float b[],
float d,
float c[])
{
c[0] = a[0] + (b[0] - a[0]) * d;
c[1] = a[1] + (b[1] - a[1]) * d;
}
Or
void lerp_2(float a[], float b[],
float d,
float c[])
{
c[0] = a[0] * (1.0f - d) + b[0] * d;
c[1] = a[1] * (1.0f - d) + b[1] * d;
}
Here, a testable implementation.
You don't need gradient (slope).
In your case you are given n - ratio between new vector and difference vector, so calculations are simple:
for (i = 0; i < 2; i++)
result[i] = a[i] + n * c[i];
for n=0.5 new point will lie in the middle betwwen a and b
In general case of arbitrary distance you need to calculate normalized (unit length) direction vector
for (i = 0; i < 2; i++)
u[i] = c[i] / len;
and multiply it's components by needed distance
for (i = 0; i < 2; i++)
result[i] = a[i] + u[i] * needed_distance;
I have a function that gets passed a linear block of memory that encodes a row-major stored higher-dimensional matrix (3d, 4d, ...).
Is there a way to cast the memory such that efficient multidimensional indexing is possible?
void do_something_in_4d(float* input, int dim1, int dim2, int dim3, int dim4) {
// input_4d = (some casting magic) input
int i = 1;
int j = 2;
int m = 3;
int n = 4;
// input_4d[i][j][m][n] == input[i*dim2*dim3*dim4 + j*dim3*dim4 + m*dim4 + n]
}
You could use C99 variable length arrays for this. Note that in case you ever need compatibility, these are not supported by any C++ version so far, and compilers like MSVC (as of 2019) don't implement them.
Now while the commonly seen form is the ability to do something like int arr[n] or int arr[w][h] as a stack variable, it does in fact work for pointers as well.
#include <stdlib.h>
#include <stdio.h>
void matrix_print(int x, int y, int z, int w, float (*matrix_4d)[y][z][w]);
void matrix_set(int x, int y, int z, int w, float (*matrix_4d)[y][z][w]);
int main()
{
int width = 3;
float matrix2[] = {0, 1, 2, 3, 4, 5};
float (*matrix_2d)[width] = (float(*)[width])matrix2;
printf("%f\n", matrix_2d[0][0]); // 0
printf("%f\n", matrix_2d[0][1]); // 1
printf("%f\n", matrix_2d[0][2]); // 2
printf("%f\n", matrix_2d[1][0]); // 3
printf("%f\n", matrix_2d[1][1]); // 4
printf("%f\n", matrix_2d[1][2]); // 5
int x=2,y=3,z=4,w=5;
float *matrix4 = malloc(sizeof(float)*x*y*z*w);
float (*matrix_4d)[y][z][w] = (float (*)[y][z][w]) matrix4;
matrix_set(x, y, z, w, matrix_4d);
printf("1D matrix\n");
for (int i = 0; i < x*y*z*w; ++i)
printf("%f\n", matrix4[i]); // 0 to 119
matrix_print(x, y, z, w, matrix_4d);
}
void matrix_set(int x, int y, int z, int w, float (*matrix_4d)[y][z][w])
{
int i = 0;
for (int xi = 0; xi < x; ++xi)
for (int yi = 0; yi < y; ++yi)
for (int zi = 0; zi < z; ++zi)
for (int wi = 0; wi < w; ++wi, ++i)
matrix_4d[xi][yi][zi][wi] = i;
}
void matrix_print(int x, int y, int z, int w, float (*matrix_4d)[y][z][w])
{
printf("4D\n");
printf("%f\n", matrix_4d[0][0][0][0]); // 0
printf("%f\n", matrix_4d[0][0][0][1]); // 1
printf("%f\n", matrix_4d[0][0][1][0]); // 5
printf("%f\n", matrix_4d[0][1][0][0]); // 20
printf("%f\n", matrix_4d[1][0][0][0]); // 24
printf("%f\n", matrix_4d[1][2][3][4]); // 119
}
You can cast the input pointer to a 3-D variable-length array pointer type and access it like a 4-D array:
float (*input_4d)[dim2][dim3][dim4] = (float (*)[dim2][dim3][dim4])input;
For readability, I'd introduce a typedef for the 3-D array:
typedef float f3d[dim2][dim3][dim4];
f3d *input_4d = (f3d *)input;
Assuming C99 compatibility, then yes, you can cast the array as a multi dimensional VLA.
float (*input_4d)[dim2][dim3][dim4] = (float(*)[dim2][dim3][dim4])input;
Goal: I am trying to create a ray tracer in C. I just added in a light source that should give each of my three spheres a shading effect based on where the light is. If the light is to the left of all of them, a shadow should be cased on the right.
Problem: When changing the light intensities and position of the light, all the spheres are changed uniformly. The spheres will be more or less lit equally and there is no variation of lighting on individual pixels on the sphere.
My debugging attempts: I have tried looking through the variable outputs by printing out a lot of different info and I think the source comes from my variable
diffuse_light_intensity
which does not change much (through all the iterations on the screen the value changes twice when it should be changing quite often due to the angles of the light on the surface changing quite a bit)
My Code: (my theory is the problem lies in scene_intersect() or cast_ray())
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <limits.h>
typedef struct {
float position[3];
float intensity;
} Light;
typedef struct {
float diffuse_color[3];
} Material;
typedef struct {
float center[3];
float radius;
Material material;
} Sphere;
int arrSub(const float arr1[], const float arr2[], float subArr[], int length) {
/*
Requires 3 equally sized arrays (denoted as length),
arr1 - arr2 will result in the third array subArr
*/
for (int i = 0; i < length; i++) {
subArr[i] = arr1[i] - arr2[i];
}
return 0;
}
int arrAdd(const float arr1[], const float arr2[], float addArr[], int length) {
/*
Requires 3 equally sized arrays (denoted as length),
arr1 + arr2 will result in the third array subArr
*/
for (int i = 0; i < length; i++) {
addArr[i] = arr1[i] + arr2[i];
}
return 0;
}
int arrScalarMult(const float arr1[], float scalar, float newArr[], int length) {
/*
Requires 3 equally sized arrays (denoted as length),
arr1 - arr2 will result in the third array subArr
*/
for (int i = 0; i < length; i++) {
newArr[i] = arr1[i] * scalar;
}
return 0;
}
float dotProduct(const float arr1[], const float arr2[], int length) {
/*
Returns the dot product of two equal sized arrays
(treated as vectors)
a (dot) b = a1b1 + a2b2 + ... anbn
*/
float result = 0;
for (int i = 0; i < length; i++) {
result += arr1[i] * arr2[i];
}
return result;
}
int normalize(float arr[], int len) {
//Normalize a vector (array)
float sumSqr;
float norm;
for (int i = 0; i < len; i++) {
sumSqr += arr[i] * arr[i];
}
norm = sqrt(sumSqr);
for (int i = 0; i < len; i++) {
arr[i] = arr[i] / norm;
}
return 0;
}
bool ray_intersect(const float origin[], const float dir[], float t0, Sphere s) {
/*
Ray-Sphere Intersection
Vectors:
origin (the zero vector)
dir (direction vector)
L (vector from origin to center of sphere)
Scalars:
tca
d2
thc
t0
t1
*/
float L[3] = {0,0,0}; //The zero vector
arrSub(s.center, origin, L, 3); //L is now the vector from origin to the sphere's center
float tca = dotProduct(L, dir, 3); //Projection of L onto dir
float d2 = dotProduct(L, L, 3) - tca*tca;
if (d2 > s.radius * s.radius) return false; //There is no intersection, so return false.
float thc = sqrtf((s.radius*s.radius - d2));
t0 = tca - thc;
float t1 = tca + thc;
if (t0 < 0) {
t0 = t1;
}
if (t0 < 0) return false;
return true;
}
bool scene_intersect(const float origin[], const float dir[], const Sphere s[], int len, float hit[], float N[], Material * ptr_m) {
float sphere_dist = INT_MAX;
for (size_t i=0; i < len; i++) {
float dist_i;
if (ray_intersect(origin, dir, dist_i, s[i]) && dist_i < sphere_dist) {
sphere_dist = dist_i;
float dirDist[3];
arrScalarMult(dir, dist_i, dirDist, 3);
arrAdd(origin, dirDist, hit, 3);
float hitMinusCenter[3];
arrSub(hit, s[i].center, hitMinusCenter, 3);
normalize(hitMinusCenter, 3);
N[0] = hitMinusCenter[0];
N[1] = hitMinusCenter[1];
N[2] = hitMinusCenter[2];
* ptr_m = s[i].material;
}
}
return sphere_dist<1000;
}
int cast_ray(const float origin[], const float dir[], const Sphere s[], const Light l[], int l_size, unsigned char colorArr[]) {
float point[3], N[3];
Material m;
Material * ptr_m = &m;
if (!scene_intersect(origin, dir, s, 3, point, N, ptr_m)) {
//background
colorArr[0] = 5; //red
colorArr[1] = 100; //green
colorArr[2] = 250; //blue
} else {
float diffuse_light_intensity = 0;
float light_dir[3];
for (size_t i = 0; i < l_size; i++) {
arrSub(l[i].position, point, light_dir, 3);
normalize(light_dir, 3);
diffuse_light_intensity += l[i].intensity * ((0.f >= dotProduct(light_dir, N, 3) ? (0.f) : (dotProduct(light_dir, N, 3))));
}
//light up pixel
colorArr[0] = m.diffuse_color[0] * diffuse_light_intensity;
colorArr[1] = m.diffuse_color[1] * diffuse_light_intensity;
colorArr[2] = m.diffuse_color[2] * diffuse_light_intensity;
}
return 0;
}
int render(const Sphere s[], const Light l[], int l_length) {
/*
Creates image in a new color each step.
*/
const int width = 1024;
const int height = 768;
FILE *fp = fopen("fourth.ppm", "wb"); // Write in binary mode
(void) fprintf(fp, "P6\n%d %d\n255\n", width, height);
float fov = 3.1415926535/2.; // Field of View
#pragma omp parallel for
for (size_t j = 0; j < height; j++) {
for (size_t i = 0; i < width; i++) {
float x = (2*(i+.5)/(float)width - 1)*tan(fov/2.)*width/(float)height;
float y = -(2*(j+.5)/(float)height - 1)*tan(fov/2.);
float dir[] = {x,y,-1};
normalize(dir, 3);
unsigned char color[3];
const float origin[] = {0,0,0};
cast_ray(origin, dir, s, l, l_length, color);
(void) fwrite(color, 1, 3, fp);
}
}
(void) fclose(fp);
return 0;
}
int main(void) {
Material red = {255,0,0};
Material pink = {150,10,150};
Material gold = {255, 195, 0};
//Populate with spheres
Sphere s[3];
Sphere originalS = {{-3,0,-16},2,gold};
Sphere bigS = {{-1.0, -1.5, -12}, 3, red};
Sphere anotherS = {{7,5,-18},2,pink};
s[0] = originalS;
s[1] = bigS;
s[2] = anotherS;
//Add light source
Light l[1];
Light test_light = {{-20,20,20}, 1.5};
l[0] = test_light;
render(s,l, 1);
printf("Run success!\n");
return 0;
}
If any clarification is needed on my code please let me know, I am quite new to both C and stackoverflow.
There's a fundamental error in ray_intersect where you're passing the t0 variable by value, and not as a pointer, and therefore in the scene_intersect function its value is always zero.
The other problem is that you don't initialize the sumSqr in the normalize function, resulting in that function returning NaN for each vector component.
With those two fixed I get something approximating shaded balls. The errors in that image are caused by failing to ensure that your output pixel values fall in the range [0, 255].
NB: both of these first errors are detected if you turn on full compiler error checking, warning you of uninitialised variables being used.
This struct allows representing arbitrary size matrices, where M is the number of rows, N is the number of columns and data is a pointer to M*N values of type double stored by rows.
struct matrix {
size_t M, N;
double *data;
};
struct matrix *mat_directsum(const struct matrix *a, const struct matrix *b);
The function mat_directsum accepts two pointers to arrays as a parameter and should return to the direct sum, dynamically allocated on the heap.
Example:
A.M = 2
A.N = 3
A.data = (1, 1, 2, 0, 1, -3)
Example of direct sum function
I just need a few tips on how to set the function, just to see how others work with arrays of this type, because the only way that comes to mind is an iterative methods with many loops, however, it is enough work long and ingenious, I would like to know if there are easier method to solve it. Thank you
ps.
(memory allocation is not a problem of course)
EDIT
I solved like that:
struct matrix *mat_directsum(const struct matrix *a, const struct matrix *b) {
struct matrix *c = malloc(sizeof(struct matrix));
c->M = a->M + b->M;
c->N = a->N + b->N;
int n = c->M * c->M;
double *dati = calloc(n, sizeof(double));
int t = 0;//index new array
int y = 0;//index first mat
int z = 0;//index second mat
for (int i = 0; i < c->N; i++) {
if (i < a->N) {//first mat
for (int j = 0; j < c->M; j++) {
if (j < a->M) {
dati[t] = a->data[y];
y++;
}
t++;
}
} else {//second mat
for (int j = 0; j < c->M; j++) {
if (j >= a->M) {
dati[t] = b->data[z];
z++;
}
t++;
}
}
}
c->data = dati;
return c;
}
I don't know how to do it which only one for loop
//macro which will point to an element indexed at [xe][ye]
#define ELEMENT(data,rows,columns,xe,ye) (data+((xe)*(columns)+(ye)))
struct matrix
{
size_t M, N;
double *data;
};
//won't mind changing the return type from "struct matrix*" to "struct matrix"
struct matrix mat_directsum(const struct matrix *a, const struct matrix *b)
{
int x;
struct matrix res;
res.M = a->M + b->M;
res.N = a->N + b->N;
//using calloc will set the memory to zero i.e all the bytes will be set to zero.
res.data = (double*)calloc(res.M * res.N, sizeof(double));
if(res.data == NULL)
{
return res;
}
for(x = 0; x < a->M; ++x)
{
memcpy(ELEMENT(res.data, res.M, res.N, x, 0), ELEMENT(a->data, a->M, a->N, x, 0), a->N * sizeof(double));
}
for(x = 0; x < b->M; ++x)
{
//note the offset by [a->M][a->N] while accessing elements of res.
memcpy(ELEMENT(res.data, res.M, res.N, x + a->M, a->N), ELEMENT(b->data, b->M, b->N, x, 0), b->N * sizeof(double));
}
return res;
}
struct matrix res = mat_directsum(&a, &b);
if(res.data != NULL)
{
free(res.data);
}
Besides the error n = c->M * c->M, spotted by M.M (what a coincidence of Ms!), your solution has another error in the for loops: You confused the row and column numbers M and N - since the values are stored by rows, the outer loop has to be for (int i = 0; i < c->M; i++) and the inner loops have to be for (int j = 0; j < c->N; j++), so all M and N in those loops (also in the ifs) have to be swapped. Apart from that and the missing allocation error checks, your solution is fine.
I don't know how to do it which only one for loop
If you want to see an alternative approach, here's one with a helper function to insert the matrices into the sum matrix:
#include <string.h>
void mat_insert(const struct matrix *s, struct matrix *d, int r, int c)
{ // copy source matrix s to destination matrix d at row r, column c
for (int i = 0; i < s->M; i++) // for each row
memcpy(d->data+(r+i)*d->N+c, s->data+i*s->N, s->N*sizeof*s->data);
}
struct matrix *mat_directsum(const struct matrix *a, const struct matrix *b)
{
struct matrix *c = malloc(sizeof *c); if (!c) return NULL;
c->M = a->M + b->M;
c->N = a->N + b->N;
int n = c->M * c->N;
c->data = calloc(n, sizeof *c->data); if (!c->data) return free(c), NULL;
mat_insert(a, c, 0, 0); // copy a to c at row 0, column 0
mat_insert(b, c, a->M, a->N); // copy b to c at row a->M, column a->N
return c;
}
I am trying to pass a matrix to a function by reference. The function will replace every element A[i][j] of the matrix by -A[i][j]. I first create the matrix:
float a[3][4] =
{
{1.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 0.0f},
{1.0f, 1.0f, 0.0f, 0.0f},
};
Then, I obtain the pointer to this matrix:
float*** pa = &a;
Then, I introduce the following function:
void process(float ***matrix, int nRows, int nCols){
short i;
short j;
for (i=0 ; i<nRows; i++){
for (j=0 ; j<nCols ; j++){
(*matrix)[i][j] *= -1;
}
}
}
which I call as follows:
process(pa,3,4);
My program fails to execute and returns:
Segmentation fault: 11
Any ideas?
Summary of the answers: Some notes based on the questions this question received:
I. The aforementioned function can be used, provided that a is initialized a bit differently so as to be a float**. In particular:
int numberOfRows = 3;
int numberOfColumns = 4;
float **a = (float **) malloc(sizeof (float *) * numberOfRows);
for (i = 0; i < numberOfRows; ++i) {
a[i] = (float *) malloc(sizeof (float) * numberOfColumns);
}
and then, it is passed to the function process as process(&a, 3,4);.
II. Alternatively, one may use the function:
void multi_by_minus(float *matrix, int nRows, int nCols) {
short i,j;
for (i = 0; i < nRows; i++) {
for (j = 0; j < nCols; j++) {
matrix[i * nCols + j] *= -1;
}
}
}
which treats the matrix as an one-dimensional array. In that case we simply invoke it as multi_by_minus(&a, 3, 4);
III. Finally, we may use the method:
void process2(int nRows, int nCols, float (*matrix)[nCols]) {
short i, j;
for (i = 0; i < nRows; i++) {
for (j = 0; j < nCols; j++) {
matrix[i][j] *= -1;
}
}
}
to which we provide a pointer to a, i.e., we invoke it like process2(3,4,&a);. In this way, we acquire access to the elements of the matrix in 2D.
There is no need for the triple pointer since you are already supplying the memory. You would use that if you were to allocate the memory inside de function.
You can't index a 2 dimension matrix without supplying at least the size of 1 dimension. The reason is that the compiler needs to generate code to access the correct offset taking into account both dimensions. In this particular case, I suggest passing a simple pointer and indexing as a 1D array, like this:
void process(float *matrix, int nRows, int nCols){
short i;
short j;
for (i=0 ; i<nRows; i++){
for (j=0 ; j<nCols ; j++){
matrix[i * nCols + j] *= -1;
}
}
}
You can then call it like this:
process((float*)a,3,4);
This way you manually index your buffer.
You have to change the signature of the function to this:
void process(float (*matrix)[3][4], int nRows, int nCols){
And when calling the function, use this:
process(&a, 3, 4);
If you put the nCols parameter before the matrix parameter, you can pass the two-dimensional matrix and use it in the natural way, without extra * operators or index arithmetic:
void process(int nRows, int nCols, float (*matrix)[nCols])
{
for (short i = 0 ; i < nRows; i++)
{
for (short j = 0; j < nCols; j++)
{
matrix[i][j] *= -1;
}
}
}
Then you call process like this:
process(3, 4, matrix);
Incidentally:
Unless there is special reason for making i and j short, you should declare them int. int is defined to be the “natural” size for integers on the target platform.
So easy, if you have a matrix:
int m[2][2]={{1,0},{0,1}};
and you want to define a pointer to m, so you must declare:
int (*mptr)[2][2];
mprt=m; // or mptr=&m; is the same.
and you can use it to point to elements of the matrix m.
(*mptr)[i][j]....