How to pass pointers to vector extensions in C - c

I'm trying to use GCC's vector extensions, the exact code that I tried is:
typedef float Vector4 __attribute__ ((vector_size (16)));
void defVector(Vector4* v, float x,float y,float z,float w){
v[0] = x;
v[1] = y;
v[2] = z;
v[3] = w;
}
int main(int argc, char* argv){
Vector4 a;
defVector(&a, 1, 2, 3, 4);
}
and keep getting errors:
incompatible types when assigning to type ‘Vector4 {aka __vector(4) float}’ from type ‘float’
v[0] = x;
Can't dereference it too or I get another error.
I would like to not copy the entire thing to the function stack every time I use it, and it's a necessity to make pointers to the return values like
int someFunc(Vector4 v, Vector4* r){
...
r[0] = return_value;
return 0;
}
I tried everything I know to access the values inside the funtion.
What I'm missing here?

Based on the OP's example in which a local function gets a "vector-extension" pointer:
#include <stdio.h>
#include <stdint.h>
typedef float Vector4 __attribute__ ((vector_size (16)));
void defVector(Vector4 *v,float a, float b);
void defVector(Vector4 *v,float a, float b){
v[0] = *(Vector4*)&a;
v[1] = *(Vector4*)&b;
a = *(float*)&v[0] + 1.2;
b = *(float*)&v[1] + 2.1;
printf("%f,%f,%u",a,b,\
(uint32_t)sizeof(Vector4)/(uint32_t)sizeof(float));
}
int main(void) {
static Vector4 vectorA;
static float x1 = 3.4;
static float x2 = 4.3;
defVector(&vectorA,x1,x2);
}
This code will print (demo): 4.6,6.4,4 , so the value of two float were assigned to two units (being the number of units sizeof(Vector4)/sizeof(float)) of a Vector4 type variable.

Related

Function Pointer with void* return and void* parameters

I wrote a function pointer that has all void* so that it can be used for any numeric value
int
float
double.
But it is working only for the int addition function
For float and double addition functions, it throws compile time error.
Why is that so ?
If you uncomment the last two printf lines, you would receive error
#include<stdio.h>
int int_add(int x, int y) {
return x + y;
}
float float_add(float x, float y) {
return x + y;
}
double double_add(double x, double y) {
return x + y;
}
void* do_operation(void* (*op)(void*, void*), void* x, void* y) {
return op(x, y);
}
void main(void) {
printf("Sum= %d\n",(int*) do_operation(int_add, 1, 2));
/*printf("Sum= %f\n",(float*) do_operation(float_add, 1.20, 2.50));*/
/*printf("Sum= %lf\n",(double*) do_operation(double_add, 1.20, 2.50));*/
}
void * is a pointer type. You're not passing pointers, you're passing values, so that's not going to compile. It accidentally "works" for int because pointers themselves are represented as integers by most C compilers.
If you pass pointers to int, float, and double instead of the int, float, and double themselves, you will avoid that compiler error. You'd also need to change int_add and friends to take pointers, and you'd have to make sure you dereferenced the pointers before using them. You'll also have to return pointers, which means you'll have to malloc some memory on the heap, because the stack memory assigned to your local variables will be invalid once your function exits. You'll then have to free it all later... in the end, this is going to result in something considerably more complicated than the problem it appears you are trying to solve.
I have to ask why you are trying to do this? C is really not the best language for this type of pattern. I'd suggest just calling the int_add, float_add, etc. functions directly instead of trying to abstract them in this way.
So as per #charles-srstka suggestion I rewrote the code and then it worked as I wanted
#include<stdio.h>
#include<stdlib.h>
int* int_add(int *x, int *y) {
int *c = (int *)malloc(sizeof(int));
*c = *(int*)x + *(int*)y;
return c;
}
float* float_add(float *x, float *y) {
float *c = (float*)malloc(sizeof(float));
*c = *(float*)x + *(float*)y;
return c;
}
void* do_operation(void* (*op)(void*, void*), void* x, void* y) {
return op(x, y);
}
void main(void) {
int a = 1;
int b = 2;
int *c;
c = do_operation(int_add, &a, &b);
printf("%d\n",*c);
free(c);
float x = 1.1;
float y = 2.2;
float *z;
z = do_operation(float_add, &x, &y);
printf("%f\n",*z);
free(z);
}

Returning a struct in a void func()

I'm trying to compile my code from the old MS-DOS days and this doesn't seem to work with GCC:
typedef struct { int x,y,z; } vector;
inline void vect_add(vector& c,vector a, vector b)
{
c.x=a.x+b.x;
c.y=a.y+b.y;
c.z=a.z+b.z;
}
Basically I'm trying to return a struct which is later used as vector.x etc instead of rewriting it as a pointer to struct and rewriting all as vector->x etc
see (vector& c,
That is possibly valid C++, but it's not valid C.
In C, you need to use a pointer, a global var, or actually return a struct.
typedef struct { int x, y, z; } vector;
inline void vect_add(vector* c, vector a, vector b)
{
c->x = a.x + b.x;
c->y = a.y + b.y;
c->z = a.z + b.z;
}
vect_add(&c, a, b);

Pointer to multidimensional array error: Expression must have pointer-to-object type

The following code returns the error: Expression must have pointer-to-object
type. somehow the problem lies in the way I reference the parameters A, B and out which each point to a 2D array. Any help would be much appreciated.
The goal is to multiply two arrays.
#include <stdio.h>
void matrixmul(const float *A, const float *B, int m, int n, int k, float *out)
{
float value = 0.0;
int x, y, z;
for (x = 0; x < k; x++) {
for (y = 0; y < m; y++) {
for (z = 0; z < n; z++) {
float product = A[y][z] * B[z][y];
value = value + product;
printf("%lf", value);
}
out[y][x] = value;
value = 0;
}
}
}
int main(void) {
float a[2][3] = {
{ 1.0,2.0,1.0 },
{ 3.0,4.0,1.0 }
};
float b[3][1] = {1, 2, 3};
float array[2][1];
matrixmul((float *) a, (float *) b, 2, 3, 1, (float *) array);
return 0;
}
Since A is declared as const float *A in the function, A[y][z] is an invalid term. A[y] evaluates to type const float. You can't use an array operator, [z], with a float.
The same problem occurs with B and out.
You can define the function as
void matrixmul(const float A[][3], const float B[][1], int m, int n, int k, float out[][1])
{
...
}
and call the function simply as:
matrixmul(a, b, 2, 3, 1, array);
C99/C11 support variable length arrays. Assuming you can use compiler that supports C99/C11, you can define the function as
void matrixmul(int arows, int acols, int bcols,
const float A[arows][acols],
const float B[acols][bcols],
float out[arows][bcols])
{
...
}
and call the function using
matrixmul(2, 3, 1, a, b, array);
The function does not know the dimensions of your array, so it does not know how to calculate the address of a value given the row and column. You can use a function's arguments to define the dimensions of your matrix, however. You will have to rearrange the arguments in your function such that the arguments specifying the dimensions appear before the array. Using your function, it might look something like this:
void matrixmul(int m, int n, int k, const float A[m][n], const float B[n][m], float out[m][k])
By the way, I haven't really read fully through the function, but is out[y][k] = value; supposed to be out[y][x] = value;?

Initializating struct error: 'theGrid' being used without being initialized

I am trying to create a 3d grid for my OpenCl/GL fluid. The problem Im having is that for some reason the my grid initialization function does not work properly. Here is my *.h, *.c setup and (at the end) call in main:
(grid.h):
#if RunGPU
#define make_float3(x,y,z) (float3)(x,y,z)
#define make_int3(i,j,k) (int3)(i,j,k)
#else
typedef struct i3{
int i,j,k;
} int3;
typedef struct f3{
float x,y,z;
} float3;
#define __global
#define make_float3(x,y,z) {x , y , z}
#define make_int3(x,y,z) {x , y ,z}
#endif
typedef struct grid3 * grid3_t; // u,v,w
typedef struct grid * grid_t; // p
struct grid3 {
__global float3* values_;
__global float * H_;
__global float * h_;
int dimx_;
int dimy_;
int dimz_;
} ;
struct grid {
__global float * values_;
int dimx_;
int dimy_;
int dimz_;
};
void grid3_init(grid3_t grid,__global float3* vel,__global float* H,__global float *h, int X, int Y, int Z);
(grid.c):
void grid3_init(grid3_t grid,__global float3* val,__global float* H,__global float *h, int X, int Y, int Z){
grid->values_ = val;
grid->H_ = H;
grid->h_ = h;
grid->dimx_ = X;
grid->dimy_ = Y;
grid->dimz_ = Z;
}
In main im initializing my grid like so:
int main(int argc, char** argv)
{
const int size3d = Bx*(By+2)*Bz;
const int size2d = Bx*Bz;
float3 * velocities = (float3*)malloc(size3d*sizeof(float3));
float * H = (float*)malloc(size2d*sizeof(float));
float * h = (float*)malloc(size2d*sizeof(float));
for(int i = 0; i < size3d; i++){
float3 tmp = make_float3(0.f,0.f,0.f);
velocities[i] = tmp;
if(i < size2d){
H[i] = 1;
h[i] = 2;
}
}
grid3_t theGrid;
grid3_init(theGrid, velocities, H, h, Bx, By, Bz); // <- ERROR OCCURS HERE
}
The error im getting is during runtime - "Run-Time Check Failure #3 - The variable 'theGrid' is being used without being initialized". But thats precisely the job of grid3_init?
As im trying to write code to work for both Host and GPU I have to sacrifice the use of classes and work strictly with structs - which I have less experience with.
At this point I dont really know what to google either, I appriciate any help i can get.
struct grid3 theGrid;
grid3_init(&theGrid, velocities, H, h, Bx, By, Bz);
You need to create grid3 instance and pass its pointer to grid3_init. Your existing code just uses uninitialized pointer.

C Typedef Struct / Union auto-cast

Im having a small math library for 3d vector and Im trying to "unify" it.
Instead of having multiple typedef struct for vector3f, vector3i, color3, angles etc... Im trying to put everything inside the same struct like this:
typedef struct
{
union
{
float x;
float r;
float ax;
int x_int;
};
union
{
float y;
float g;
float ay;
int y_int;
};
union
{
float z;
float b;
float az;
int z_int;
};
} vec3;
Everything works peachy as long as the type is float, however when it falls to int Im having some strange values (which is understandable). My question is: Is there a way to cast directly/automatically inside the structure definition or I have to create extra functions to typecast between float and int?
Due to the answers below, maybe I should modify my original question to the following:
What is the best way to "unify" (and by unify I mean have like 1 struct) to be able to handle at the same time the following:
vector3f (float x,y,z)
vector3i (int x,y,z)
RGB (float r,g,b)
RGB (unsigned char r,g,b)
euler angle (ax, ay, az)
Thanks in advance!
If you mean that you want to put '360.0f' into float z of a union and have int z_int == 3, or vice versa, you can't. That is not the purpose of a union, and the binary representation of 3 (an integer) and 3.0 (a floating point value) are dissimiliar.
However, you could just remove the int and cast one of the floats to an int.
#include <stdio.h>
#include <stdlib.h>
typedef struct genericStruct
{
void *valueOne;
void *valueTwo;
}GS;
int main()
{
GS *gs = malloc(sizeof(*gs));
int valueInt = 10;
float valueFloat = 3.141592653589;
int *inputIntPtr = (int*)malloc(sizeof(int));
float *inputFloatPtr = (float*)malloc(sizeof(float));
void *voidPtr = NULL;
*inputIntPtr = valueInt;
*inputFloatPtr = valueFloat;
voidPtr = inputIntPtr;
gs->valueOne = voidPtr;
int *outputIntPtr = (int*)malloc(sizeof(int));
outputIntPtr = gs->valueOne;
printf("Input ptr = %d\n", *inputIntPtr);
printf("Output ptr = %d\n", *outputIntPtr);
voidPtr = inputFloatPtr;
gs->valueTwo = voidPtr;
float *outputFloatPtr = (float*)malloc(sizeof(float));
outputFloatPtr = gs->valueTwo;
printf("Input ptr = %f\n", *inputFloatPtr);
printf("output ptr = %f\n", *outputFloatPtr);
free(gs);
free(inputIntPtr);
free(inputFloatPtr);
free(outputIntPtr);
free(outputFloatPtr);
return 0;
}
And this what I meant by using void types.
This is a small piece of code that i wrote for you.It should do the job.I hope i was able to do what you asked for...
typedef struct{
void *ptr1;
void *ptr2;
void *ptr3;
}VEC;
main(){
VEC v ;
VEC *ptr;
int a = 5;
double b = 6;
float c = 7;
v.ptr1 = NULL;
v.ptr2 = NULL;
v.ptr3 = NULL;
ptr = &v;
v.ptr1 = (int *)&a;
ptr->ptr1 = (int *)&a;
v.ptr2 = (double *)&b;
ptr->ptr2 = (double *)&b;
v.ptr3 = (float *)&c;
ptr->ptr3 = (float *)&c;
printf("%d\n",*(int *)v.ptr1);
printf("%d\n",*(int *)(ptr->ptr1));
printf("%lf\n",*(double *)v.ptr2);
printf("%lf\n",*(double *)(ptr->ptr2));
printf("%f\n",*(float *)v.ptr3);
printf("%f\n",*(float *)(ptr->ptr3));
}
Or change all variables to void pointer type and then cast them to float or integer. Is it OK?

Resources