0

I have an array of floating point values which represents an a series of complex numbers (so the first value of the array, say x[0], is the real part of the first complex number, x[1] is the imaginary part of the first complex number, x[2] is the real part of the second, and so on...).

My problem is that I want to be able to access these numbers as if they were in a structure format, i.e.

struct cmpx
{
    float real;
    float imag;
};
typedef struct cmpx COMPLEX;

So I create a union like so:

typedef union complexdata 
{
    float numbers[2];
    COMPLEX cart; //Stands for cartesian

}complexpair;

So my simplified main() function looks like this:

void main(void)
{   
float x[10]={1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0};// In reality this is much longer 
complexpair *x_ptr;


x_ptr->numbers[0] = x;
}

This is clearly wrong and I get the error:

a value of type "float *" cannot be assigned to an entity of type "float" for the line "x_ptr->number[0] = x;"

Is it possible to use a pointer of union type the way I've defined above to point to an array of floating point values? So that I can access the data in the structure/cartesian format as well treating it as an array of two floating point values?

Thank you for your help.

UPDATE: Just to make it clear why I want to do this;

I have an FFT function with the prototype:

 void fft(COMPLEX *Y, int M, COMPLEX *w) 

So would like to pass x as the first argument, I have variable w which is exactly the same format as x. When I try something like:

fft((COMPLEX)x->cart, N, (COMPLEX)w_ptr->cart);

this throws an error. I hope the motivation behind this is clearer? Many thanks.

bluefocs
  • 63
  • 1
  • 9
  • The w is a typo, now changed. – bluefocs Mar 07 '14 at 15:27
  • I need some more information to help. What exactly do you want as the outcome? For example, do you want to be able to access the first `1.0` by typing something like `x_ptr->cart.real`, and the first `0.0` by typing `x_ptr->cart.imag`? – Utkan Gezer Mar 07 '14 at 15:42
  • Yes, but also being able to access them as x_ptr->numbers[0] and x_ptr->numbers[1], hence the union. – bluefocs Mar 07 '14 at 16:31
  • Shouldn't the fft call work with the right casts to a pointer of COMPLEX as in `fft((COMPLEX *)x_ptr, N, (COMPLEX *)w_ptr);`? – Lutz Lehmann Mar 08 '14 at 14:35

2 Answers2

0

EDITED after OP's comment.

You should be able to do what you want, You'll need to reformat that long initializer (on the stack):

void main(void)
{   
    complexpair x[5]= { {1.0,0.0},
                        {1.0,0.0},
                        {1.0,0.0},
                        {1.0,0.0},
                        {1.0,0.0}  };// In reality this is much longer

    complexpair *x_ptr = x;

}   

OR just re-cast the data:

void main(void)
{   
    float x[10]={1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0};// In reality this is much longer 

    complexpair *x_ptr = (complexpair *)x;
}
problemPotato
  • 589
  • 3
  • 8
0

Well, I unfortunately was unable to understand what exactly you are desiring to have, but I do have a vague guess about what you want from the upper half of your question, so here's what I've understood:

  • You have an array of float values that are to be interpreted as real and imag parts of the COMPLEX data type.
  • 2n - 1'th element of the array is to be interpreted as the real part of the n'th element, and 2n'th element is to be interpreted as the imag part.

  • Now this will be an assumption: You want to access them in some desirable fashion.

If I am right about those, you can achieve that by using pointers in a smart fashion. With the declaration/initialization of float x[2n], you have the following in your hands:

float x[10] = { 1.0, 1.5, 2.0, 2.5, 3.0, ... } //changed numbers for better distinction

Inside memory, you have the following for the thing above:

 1.0             1.5             2.0             2.5             3.0             ...

//addresses or memory locations of which are:
  x              x+1             x+2             x+3             x+4             ...

Now, by simply making the assignment complexpair * x_ptr = x; during initialization, or x_ptr = x; afterwards, you make the same memory locations to be accessible with following:

x_ptr                          x_ptr+1                         x_ptr+2           ...

And that's all! You now have an easy method to access all that, simply with these two lines:

...
float x[10] = { 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5 };
complexpair *x_ptr = x;
...

To access the real and imag parts of the COMPLEXes with this, you can simply write:

x_ptr[0].cart.real;     //is 1.0
x_ptr[0].cart.imag;     //is 1.5

x_ptr[2].cart.imag;     //is 3.5
x_ptr[4].numbers[0];    //is 5.0
...

For the reference, here's the whole code I have here that I've used for behavioural examination:

#include <stdio.h>

typedef struct cmpx {
    float real;
    float imag;
} COMPLEX;

typedef union complexdata {
    float numbers[2];
    COMPLEX cart;
} complexpair;

int main( ) {

    float x[10] = { 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5 };
    complexpair *x_ptr = x;

    for ( int i = 0; i < 5; i++ )
        printf( "%f %f\n", x_ptr[i].cart.real, x_ptr[i].cart.imag );

    putchar( 10 );

    for ( int i = 0; i < 5; i++ )
        printf( "%f %f\n", x_ptr[i].numbers[0], x_ptr[i].numbers[1] );

    getchar( );

    return 0;
}
Utkan Gezer
  • 3,009
  • 2
  • 16
  • 29
  • Ok thank you for your response, when I try anything like complexpair *x_ptr = x; it produces an error. I should probably add more information see updated question in a moment. – bluefocs Mar 07 '14 at 17:08
  • @bluefocs I don't understand how it can produce an error... The code above, exactly as it is, does not produce any error, just a warning. You can assign typecasted `x` to `x_ptr` to eliminate that error, as in: `complexpair *x_ptr = (complexpair *) x;` to get rid of that warning as well. But that should just be a warning, not an error... – Utkan Gezer Mar 07 '14 at 17:27
  • That's how I got around the error. I am writing this for an embedded system so the compiler can act strangely. – bluefocs Mar 07 '14 at 17:29
  • @bluefocs Regarding your last edit, the function `fft` expects an *address* to a `COMPLEX` structure, but you are giving the structure itself to it by calling it like `fft((COMPLEX)x->cart, N, (COMPLEX)w_ptr->cart);`. Typecasts there should also be completely redundant, since those values already are `COMPLEX`es. If the thing you want to achieve is to be able to manipulate `x->cart` and `w_ptr->cart` inside the `fft`, then just call the function like this: `fft(&x->cart, N, &w_ptr->cart);`. Or do you want to legitimately play around with *for example* `Y`, **not just the `*Y`**, inside `fft`? – Utkan Gezer Mar 07 '14 at 17:39
  • I just need to manipulate x->cart and w_ptr->cart within the fft function, i.e. I am bothered about the union as long it retains the COMPLEX structure, so fft(&x->cart, N, &w_ptr->cart), works. Thanks. – bluefocs Mar 07 '14 at 17:52