2

I found this structure code in a Julia Set example from a book on CUDA. I'm a newbie C programmer and cannot get my head around what it's doing, nor have I found the right thing to read on the web to clear it up. Here's the structure:

struct cuComplex {
    float   r;
    float   i;
    cuComplex( float a, float b ) : r(a), i(b)  {}
    float magnitude2( void ) { return r * r + i * i; }
    cuComplex operator*(const cuComplex& a) {
        return cuComplex(r*a.r - i*a.i, i*a.r + r*a.i);
    }
    cuComplex operator+(const cuComplex& a) {
        return cuComplex(r+a.r, i+a.i);
    }
};

and it's called very simply like this:

cuComplex c(-0.8, 0.156);
cuComplex a(jx, jy);

int i = 0;
for (i=0; i<200; i++) {
    a = a * a + c;
    if (a.magnitude2() > 1000)
        return 0;
}

return 1;

So, the code did what? Defined something of structure type 'cuComplex' giving the real and imaginary parts of a number. (-0.8 & 0.156) What is getting returned? (Or placed in the structure?) How do I work through the logic of the operator stuff in the struct to understand what is actually calculated and held there?

I think that it's probably doing recursive calls back into the stucture

float magnitude2 (void) { return return r * r + i * i; }

probably calls the '*' operator for r and again for i, and then the results of those two operations call the '+' operator? Is this correct and what gets returned at each step?

Just plain confused.

Thanks!

Paul R
  • 208,748
  • 37
  • 389
  • 560
LGTrader
  • 2,349
  • 4
  • 23
  • 29
  • 1
    this appears to be C++, and what you need to do is read a beginner book on C++ first: http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list is a good start. There are too many C++ specific constructs in that simple snippet to explain as an answer to this question. – Nim Feb 07 '11 at 15:15
  • @Nim: Not useful. What beginner topic do you think he is missing? – TheBlastOne Feb 07 '11 at 15:17
  • @TheBlastOne, hence why it's a comment... anyways, updated the original comment about the same time as your comment.. – Nim Feb 07 '11 at 15:19
  • @TheBlastOne: Objects and Operator Overloading it seems. – Matthieu M. Feb 07 '11 at 15:22
  • Can you tell me which book the sample code is from? With code as poor as this I'd like to avoid that book. – Tony Feb 07 '11 at 15:49

8 Answers8

1

Like you said cuComplex hold two values for real (r) and imaginary (i) part of a number. The constructor simply assigns the value to r and i.

The * operator are working on cuComplex numbers. The multiply and add operators will only be called if you multiply two cuComplex isntances together.

They are simply there to simplify you code. Without the operator you would have to do the add operation yourself:

cuComplex c(-0.8, 0.156);
cuComplex a(jx, jy);

// Add, both operations are equivalent.
cuComplex result1 = cuComplex(c.r + a.r, c.i + a.i);
cuComplex result2 = c + a;

As for the code

cuComplex c(-0.8, 0.156); // Create cuComplex instance called c
cuComplex a(jx, jy); // Create cuComplex instance called a

int i = 0;
for (i=0; i<200; i++) {
    a = a * a + c; // Use the * and + operator of cuComplex
    if (a.magnitude2() > 1000)
        return 0;
}

return 1;

I think that it's probably doing recursive calls back into the stucture

float magnitude2 (void) { return return r * r + i * i; }

It is not since r and i are float. The * and + operator are overloaded for cuComplex not float

Rod
  • 52,748
  • 3
  • 38
  • 55
1

r and i are members of the struct declared as float. The expression in the magnitude2 function simply does standard float arithmetic with the values stored in those members.

The operator functions defined in the struct are used when the operators * and + are applied to variable of the struct type, for instance in the line a = a * a + c.

Dave Costa
  • 47,262
  • 8
  • 56
  • 72
1

It's a C++ implementation of a complex number, providing a method to return the magnitude and operator overloads for addition and multiplication. The real (r) and imaginary (i) parts are stored separately.

a * a + c calls the overloaded methods: (a.operator*(a)).operator+(c)

It appears you have very little grasp of even C syntax (return r * r + i * i; returns r times r plus i times i), so I suggest you read a beginner's introduction to C/C++, followed by an introduction to complex numbers and then read up on operator overloading in C++.

OrangeDog
  • 36,653
  • 12
  • 122
  • 207
1

This is not a simple struct but a class ( which is basically a struct with functions ) and is C++.

cuComplex c(-0.8, 0.156);

Here he creates an instance of this class and sets the 2 values by calling the constructor ( special function that initializes the instance fields of the class ).

This probably won't make enough sense so I suggest you study a C++ book. Accelerated C++ is a good choice if you already know some programming.

SpotsWood
  • 689
  • 6
  • 11
1

The multiplication operator simply takes the real and imaginary part of argument a and add these with the real and imaginary parts of the object the operator is called upon and returns a new complex number object of the result. I've added the this pointer to clarify:

cuComplex operator*(const cuComplex& a) {
    // first constructor argument is the real part, second is the imaginary part
    return cuComplex(this->r*a.r - this->i*a.i, this->i*a.r + this->r*a.i);
}

Same goes for the addition operator. Again the copy of a new object of type cuComplex is created and returned. This time the real and imaginary part of it being the sum of the respective fields of this object and the argument.

cuComplex operator+(const cuComplex& a) { return cuComplex(this->r+a.r, this->i+a.i); }

For the loop, it seems the imaginary number a is multiplied with itself (resulting in a rotation in the Re-Im-plane and and a constant imaginary c is added in each iteration until the magnitude (lenght) of the result exceeds a certain threshold.

Note that both the operator* and operator+, as well the function magnitude2() are members of structure cuComplex and thus the this pointer is available.

Hope that helps.

Arne
  • 1,111
  • 2
  • 11
  • 22
0

You should tag this question as C++, not C (even if you have a struct, this one has a constructor and redefines operators which are typical object-oriented concepts).

This structure defines complex numbers, allows to multiply (via operator*), add them (via operator+) and get their module (via magnitude2).

At the beininning; you have one constant complex number, c, and a, another complex number which is not constant, given by user probably via coordinates jx and jy. At each iteration of the loop, a is mutliplied by itself and c is added to this result.

If at some point a has got a module greater than 1000, the loop ends. I guess this is a test program to see how the module of a grows according to initial conditions given by a user.

Emmanuel
  • 13,935
  • 12
  • 50
  • 72
0

If you are familiar with the concept of classes replace the word "struct" with "class" it makes it much easier to understand.

The "class" contains two variables r and i, a constructor that takes two float args, an operator to multiply, an operator to add, and a function to calculate the magnitude.

SidJ
  • 669
  • 12
  • 29
0

In C++ simply use std::complex<float>.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • 2
    @downvoter: please explain you downvote of an old answer, so that others can learn from your (lack of) insight – Cheers and hth. - Alf Jan 20 '12 at 11:48
  • 1
    I wasn't the downvoter, but if I were to hazard a guess why, it would be because this is an NVIDIA CUDA question, not C++, and CUDA doesn't have C++ standard library support. There is no `std::complex` in CUDA. – talonmies Feb 23 '12 at 06:00