Numerical Recipes Forum  

Go Back   Numerical Recipes Forum > Numerical Recipes Third Edition Forum > General Hints, Tips, and Tricks for Using NR3

Reply
 
Thread Tools Rate Thread Display Modes
  #1  
Old 02-06-2010, 03:45 AM
perr perr is offline
Registered User
 
Join Date: Oct 2009
Posts: 8
MatComplex

Hi,

Why isn't "MatComplex" defined in "nr3.h"?

In "nr3.h" I find several type definitions, e.g. "VecDoub" and "MatDoub". I also find "VecComplex", but "MatComplex" is missing.

Despite this, in the ebook (third edition), it says: "Matrices:
MatInt, MatUint, MatChar, MatUchar, MatLlong, MatUllong, MatDoub,MatComplex, and MatBool."

I have the source code "NR_C302", which I interpret as version 3.02.

Anyone know anything about this?

Best regards, perr
Reply With Quote
  #2  
Old 02-07-2010, 02:33 PM
davekw7x davekw7x is offline
Registered User
 
Join Date: Jan 2008
Posts: 368
Quote:
Originally Posted by perr View Post
...
Anyone know anything about this?
I will make an observation (but I wouldn't dream of trying to put words into the Authors' mouths).

Since none of the NR routines use MatComplex, leaving its definition out of nr3.h doesn't seem to be a big shortcoming.

However...

If you want to experiment with it, try putting the following into your source code somewhere:
Code:
#include "nr3.h"
typedef const NRmatrix<Complex> MatComplex_I;
typedef NRmatrix<Complex> MatComplex, MatComplex_O, MatComplex_IO;
For example:
Code:
#include "../nr3.h"
typedef const NRmatrix<Complex> MatComplex_I;
typedef NRmatrix<Complex> MatComplex, MatComplex_O, MatComplex_IO;

int main()
{
    // The "empty" constructor
    MatComplex y;

    // Make an array that can be used to initialize a MatComplex:
    Complex z[] = {
        Complex(1.1,.1), Complex(.2,.3), Complex(.4,.5), Complex(.6,.7),
        Complex(1.2,.2), Complex(.3,.4), Complex(.5,.6), Complex(.7,.8),
        Complex(1.3,.3), Complex(.4,.5), Complex(.6,.7), Complex(.8,.9)
    };

    // Create an object that is initialized from the array
    MatComplex mc (3, 4, z);

    // Overloaded assignment operator
    y = mc;

    int i, j;
    cout << "mc.nrows() = " << mc.nrows() 
         << ", mc.ncols() = " << mc.ncols() << endl;

    //
    // Add 42 to each element and print using real() and imag()
    // member functions of the std::complex<double> elements
    //
    cout << "mc[0][0].real() = " << mc[0][0].real()
         << ", mc[0][0].imag() = " << mc[0][0].imag()
         << endl << endl;
    for (i = 0; i < mc.nrows(); i++) {
        for (j = 0; j < mc.ncols(); j++) {
            mc[i][j] += 42.0;
            cout << "  (" << mc[i][j].real() << "," << mc[i][j].imag() 
                 << ")";
        }
        cout << endl;
    }
    cout << endl;


    cout << "y.nrows() = " << y.nrows() 
         << ", y.ncols() = " << y.ncols() << endl;

    //
    // Print the copy of the original matrix, 
    // using the std::complex overloaded << operator
    //
    cout << "y[0][0] = " << y[0][0] << endl << endl;
    for (i = 0; i < y.nrows(); i++) {
        for (j = 0; j < y.ncols(); j++) {
            cout << "  " << y[i][j];
        }
        cout << endl;
    }

    return 0;
}
Output:
Code:
mc.nrows() = 3, mc.ncols() = 4
mc[0][0].real() = 1.1, mc[0][0].imag() = 0.1

  (43.1,0.1)  (42.2,0.3)  (42.4,0.5)  (42.6,0.7)
  (43.2,0.2)  (42.3,0.4)  (42.5,0.6)  (42.7,0.8)
  (43.3,0.3)  (42.4,0.5)  (42.6,0.7)  (42.8,0.9)

y.nrows() = 3, y.ncols() = 4
y[0][0] = (1.1,0.1)

  (1.1,0.1)  (0.2,0.3)  (0.4,0.5)  (0.6,0.7)
  (1.2,0.2)  (0.3,0.4)  (0.5,0.6)  (0.7,0.8)
  (1.3,0.3)  (0.4,0.5)  (0.6,0.7)  (0.8,0.9)
Notes:

Arithmetic and I/O operations on the individual elements are defined by the std::complex stuff in the C++ Standard Library.

Matrix operations (arithmetic or I/O) are not defined in nr3.h for any of the matrix or vector typedefs.

Regards,

Dave

Last edited by davekw7x; 02-07-2010 at 07:10 PM.
Reply With Quote
  #3  
Old 06-24-2010, 11:50 AM
SteveV45 SteveV45 is offline
Registered User
 
Join Date: Jun 2010
Posts: 2
First off, thank you very much for your post Dave, it was a big help for me. After using your approach to creating NRmatrix<Complex> objects I successfully modified gaussj.h to invert complex matrixes.

Code:
typedef const NRmatrix<Complex> MatComplex_I;
	typedef NRmatrix<Complex> MatComplex, MatComplex_O, MatComplex_IO;

void comgaussj(MatComplex_IO &a, MatComplex_IO &b)
{
	Int i,icol,irow,j,k,l,ll,n=a.nrows(),m=b.ncols();
	double big;
	complex<double> dum,pivinv;
	VecInt indxc(n),indxr(n),ipiv(n);
	for (j=0;j<n;j++) ipiv[j]=0;
	for (i=0;i<n;i++) {
		big=0.0;
		for (j=0;j<n;j++)
			if (ipiv[j] != 1)
				for (k=0;k<n;k++) {
					if (ipiv[k] == 0) {
						if (abs(a[j][k]) >= big) {
							big=abs(a[j][k]);
							irow=j;
							icol=k;
						}
					}
				}
		++(ipiv[icol]);
		if (irow != icol) {
			for (l=0;l<n;l++) SWAP(a[irow][l],a[icol][l]);
			for (l=0;l<m;l++) SWAP(b[irow][l],b[icol][l]);
		}
		indxr[i]=irow;
		indxc[i]=icol;
		if (a[icol][icol] == 0.0) throw("gaussj: Singular Matrix");
		pivinv=1.0/a[icol][icol];
		a[icol][icol]=1.0;
		for (l=0;l<n;l++) a[icol][l] *= pivinv;
		for (l=0;l<m;l++) b[icol][l] *= pivinv;
		for (ll=0;ll<n;ll++)
			if (ll != icol) {
				dum=a[ll][icol];
				a[ll][icol]=0.0;
				for (l=0;l<n;l++) a[ll][l] -= a[icol][l]*dum;
				for (l=0;l<m;l++) b[ll][l] -= b[icol][l]*dum;
			}
	}
	for (l=n-1;l>=0;l--) {
		if (indxr[l] != indxc[l])
			for (k=0;k<n;k++)
				SWAP(a[k][indxr[l]],a[k][indxc[l]]);
	}
}

void comgaussj(MatComplex_IO &a)
{
	MatComplex_IO b(a.nrows(),0);
	comgaussj(a,b);
}


However, I would like to be able to create a NRmatrix object by passing in a vector of complex objects like this.

Code:
#include "nr3.h"

typedef const NRmatrix<Complex> MatComplex_I;
typedef NRmatrix<Complex> MatComplex, MatComplex_O, MatComplex_IO;

int num_cav;
vector<complex<double>> M_con(num_cav*num_cav);
MatComplex a (num_cav, num_cav, M_con);
It seems like it should work if I could just overload NRmatrix correctly. Any pointers?
Reply With Quote
  #4  
Old 06-24-2010, 01:02 PM
davekw7x davekw7x is offline
Registered User
 
Join Date: Jan 2008
Posts: 368
Quote:
Originally Posted by SteveV45 View Post
...
However, I would like to be able to create a NRmatrix object by passing in a vector of complex objects like this.

Code:
...
MatComplex a (num_cav, num_cav, M_con);...
It seems like it should work if I could just overload NRmatrix correctly. Any pointers?
No need to overload NRmatrix; you can use it as-is!

Here's the thing: It is guaranteed that a C++ std::vector stores its data elements in contiguous memory. (That is, internally, the vector object stores its elements as an array.)

So, just feed your MatComplex constructor a pointer whose value is the address of the first element in your vector.

You can try either of the following:

Create an "empty" vector and use push_back() to populate it. Make sure you give it enough values so that the result has the right size.

Code:
    int nrows = 3; // Or whatever
    int ncols = 4; // Or whatever

    vector <complex<double> > M_con;

    for (int i = 0; i < nrows*ncols; i++) {
        M_con.push_back(whatever_complex_value_you_have_for_this_element);
    }

    // Create a complex matrix object that is initialized from the vector
    MatComplex mc(nrows, ncols, &M_con[0]);
Or...

You can create the vector object with the desired size and populate it with assignment statements:

Code:
    int nrows = 3;
    int ncols = 4;

    vector <complex<double> > M_con(nrows*ncols);

    for (int i = 0; i < nrows*ncols; i++) {
        M_con.[i] = (whatever_complex_value_you_have_for_this_element);
    }

    // Create a complex matrix object that is initialized from the vector
    MatComplex mc(nrows, ncols, &M_con[0]);

Taa-daa!

Quote:
Originally Posted by SteveV45
Any pointers?
Well, yeah! It's all done with pointers. (Or were you not intending a little pun there? Oh, well, I like it anyhow.)



Regards,

Dave

Footnote: NRVector objects also store their elements in arrays (guaranteed contiguous memory), so you could use my second snippet with a VecComplex if that suits your fancy. (NRVectors don't have push_back(), so my first example will work with a std::vector<complex<double> > but not a VecComplex.)

Last edited by davekw7x; 06-25-2010 at 09:13 AM.
Reply With Quote
  #5  
Old 06-25-2010, 04:19 PM
SteveV45 SteveV45 is offline
Registered User
 
Join Date: Jun 2010
Posts: 2
I went with option 2 and it worked perfectly. You're the man Dave, and thanks for the help.
Reply With Quote
Reply

Tags
matcomplex

Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -5. The time now is 07:49 AM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.