Trying to get started!


digiplant
06-18-2008, 08:37 PM
Hello, I just purchased a copy of the code and book. I'm trying to test out how it works and get started using it. Unfortunately, i'm having trouble properly utilizing the library. I'm trying to test the code by computing the incomplete beta function. My code to do this looks like:

#include <iostream>
#include "nr3.h"
#include "gamma.h"
#include "incgammabeta.h"

using namespace std;

int main()
{
double a, b, x, incompleteBeta;
a=1;
b=2;
x=0.5;
incompleteBeta = betai(a,b,x);
cout << "I(" << a << "," << b << "): " << incompleteBeta << endl;
return 0;
}


However, this code does not compile successfully. I get the message:

g++ -c -o test_inc_beta.o test_inc_beta.cc
test_inc_beta.cc: In function ‘int main()’:
test_inc_beta.cc:16: error: ‘betai’ was not declared in this scope

If I change the line where I call the betai function to:

incompleteBeta = Beta::betai(a,b,x);

I get the error message:

g++ -c -o test_inc_beta.o test_inc_beta.cc
test_inc_beta.cc: In function ‘int main()’:
test_inc_beta.cc:16: error: cannot call member function ‘Doub Beta::betai(Doub, Doub, Doub)’ without object

These errors probably are related to my lack of knowledge about how to properly call functions and the dependencies within the code.

Any advice will be invested into delving into these routines and greatly appreciated. Thanks!

davekw7x
06-18-2008, 10:47 PM
...I'm trying to test the code...

betai() is a member function of the Beta struct.

You use it as follows:
1. Declare an object of type Beta.
2. Call the member function using that object.


#include "nr3.h"
#include "gamma.h"
#include "incgammabeta.h"

using namespace std;

int main()
{
double a, b, x, incompleteBeta;
a = 1.0;
b = 0.5;
x = 0.01;

Beta myBeta;
incompleteBeta = myBeta.betai(a, b, x);

cout << "I(" << x << ";"<< a << "," << b << ") = "
<< scientific << incompleteBeta
<< endl;

return 0;
}



Output:


I(0.01;1,0.5) = 5.012563e-03


Regards,

Dave

orstats
11-02-2008, 04:41 PM
Within our project on MS Visual Studio Professional, does anyone know what is the easiest way to add all the libraries on the Numerical Recipes CD? So we can simply type ' include ' each time? Thx!

Bill Press
11-02-2008, 06:26 PM
It's probably not a good idea to add all the routines to every project. Our recommendation is to #include in your main file just the routines you need. You can figure out the dependencies by looking at http://nr.com/dependencies .

orstats
11-02-2008, 07:30 PM
I am using MS Visual Studio Prof08 as my compiler, but I get the following error when I submit the following code:

syntax error: missing ';' before identifier 'gammln'

Why should that be?

#pragma once

class gamma
{
Doub gammln(const Doub xx) {
Int j;
Doub x,tmp,y,ser;
static const Doub cof[14]={57.1562356658629235,-59.5979603554754912,
14.1360979747417471,-0.491913816097620199,.339946499848118887e-4,
.465236289270485756e-4,-.983744753048795646e-4,.158088703224912494e-3,
-.210264441724104883e-3,.217439618115212643e-3,-.164318106536763890e-3,
.844182239838527433e-4,-.261908384015814087e-4,.368991826595316234e-5};
if (xx <= 0) throw("bad arg in gammln");
y=x=xx;
tmp = x+5.24218750000000000;
tmp = (x+0.5)*log(tmp)-tmp;
ser = 0.999999999999997092;
for (j=0;j<14;j++) ser += cof[j]/++y;
return tmp+log(2.5066282746310005*ser/x);
}
Doub factrl(const Int n) {
static VecDoub a(171);
static Bool init=true;
if (init) {
init = false;
a[0] = 1.;
for (Int i=1;i<171;i++) a[i] = i*a[i-1];
}
if (n < 0 || n > 170) throw("factrl out of range");
return a[n];
}
Doub factln(const Int n) {
static const Int NTOP=2000;
static VecDoub a(NTOP);
static Bool init=true;
if (init) {
init = false;
for (Int i=0;i<NTOP;i++) a[i] = gammln(i+1.);
}
if (n < 0) throw("negative arg in factln");
if (n < NTOP) return a[n];
return gammln(n+1.);
}
Doub bico(const Int n, const Int k) {
if (n<0 || k<0 || k>n) throw("bad args in bico");
if (n<171) return floor(0.5+factrl(n)/(factrl(k)*factrl(n-k)));
return floor(0.5+exp(factln(n)-factln(k)-factln(n-k)));
}
Doub beta(const Doub z, const Doub w) {
return exp(gammln(z)+gammln(w)-gammln(z+w));
}
};

davekw7x
11-02-2008, 10:22 PM
syntax error: missing ';' before identifier 'gammln'

Why should that be?

Problem: The compiler doesn't know what a "Doub" is.
Solution: Include nr3.h

Regards,

Dave

orstats
11-02-2008, 11:48 PM
Dave: Now I get a different error when I try to add nr3.h. More specifically the error was 'Cannot open include file: 'nr3.h': No such file or directory. However, I clearly added and can see my nr3.h file in my Header Files folder in Visual Studio. Do you know what's wrong here?

//Below is the gamma.h that has been modified to include nr3.h
#pragma once
#include "nr3.h"
class gamma
{
Doub gammln(const Doub xx) {
Int j;
Doub x,tmp,y,ser;
static const Doub cof[14]={57.1562356658629235,-59.5979603554754912,
14.1360979747417471,-0.491913816097620199,.339946499848118887e-4,
.465236289270485756e-4,-.983744753048795646e-4,.158088703224912494e-3,
-.210264441724104883e-3,.217439618115212643e-3,-.164318106536763890e-3,
.844182239838527433e-4,-.261908384015814087e-4,.368991826595316234e-5};
if (xx <= 0) throw("bad arg in gammln");
y=x=xx;
tmp = x+5.24218750000000000;
tmp = (x+0.5)*log(tmp)-tmp;
ser = 0.999999999999997092;
for (j=0;j<14;j++) ser += cof[j]/++y;
return tmp+log(2.5066282746310005*ser/x);
}
Doub factrl(const Int n) {
static VecDoub a(171);
static Bool init=true;
if (init) {
init = false;
a[0] = 1.;
for (Int i=1;i<171;i++) a[i] = i*a[i-1];
}
if (n < 0 || n > 170) throw("factrl out of range");
return a[n];
}
Doub factln(const Int n) {
static const Int NTOP=2000;
static VecDoub a(NTOP);
static Bool init=true;
if (init) {
init = false;
for (Int i=0;i<NTOP;i++) a[i] = gammln(i+1.);
}
if (n < 0) throw("negative arg in factln");
if (n < NTOP) return a[n];
return gammln(n+1.);
}
Doub bico(const Int n, const Int k) {
if (n<0 || k<0 || k>n) throw("bad args in bico");
if (n<171) return floor(0.5+factrl(n)/(factrl(k)*factrl(n-k)));
return floor(0.5+exp(factln(n)-factln(k)-factln(n-k)));
}
Doub beta(const Doub z, const Doub w) {
return exp(gammln(z)+gammln(w)-gammln(z+w));
}
};

Thanks very much.

davekw7x
11-03-2008, 09:20 AM
...'Cannot open include file: 'nr3.h'...

There are two ways to solve your problem:


Either

1. Create the project properly so that the compiler can find the include files. Note that for Visual C++, simply adding files to the project is not sufficient to let the compiler know where they are at compile time! It just lets the project manager know that it is supposed to recompile if any of the project files are changed. If you aren't going to change nr3.h, it doesn't even have to be added to the project (but it doesn't hurt either).

Or

2. Put path names in your include statements so that the compiler can find them.

I like number 2, since it allows me to compile with a command line as well as when it's part of the project.

Here's the methodology for number 1.

Assuming you already have the project set up with your source files and your source files have things like #include "nr3.h"

Right-click on the project icon in the "Solution Explorer" panel on the left, and click "Properties"

In the "Properties Pages" dialog box, select
Configuration Properties->C/C++->Command Line

Then in the "Additional Options" pane enter the command line option that tells the compiler where to find nr3.h and any other header files that aren't in your project directory.

The entry will be something like /Ipathname_to_nr3_code

On my system, all of the nr3 source files are in H:\nr3\code, so I put the following in the "Additional Options" pane:

/IH:\nr3\code


Instead of H:\nr3\code, you put whatever is your path name.

Now it should build OK.

Now, for number 2: It doesn't require any changes to the Project options as long as you create the project in the proper place with respect to the nr3 source files.

As I mentioned, my nr3 source is in H:\nr3\code.

For a new project, I create a new directory under nr3.

So, to test the nr3 mglin function, I might create a directory H:\nr3\xmglin, and I put my project files there.

Now, in any source files in that directory that need nr3 files, instead of putting stuff like

#include "nr3.h"
#include "mglin.h"
.
.
.

I put

#include "../code/nr3.h"
#include "../code/mglin.h"
.
.
.


If you do this before creating your visual c++ project, then create the project in that directory, it works as it should. (At least it works for me---Your Mileage May Vary.)


Note that it is up to you to include the required nr3 header files once and only once in each file that uses them. The nr3 source files are set up so that each source file that you need is included once and only once in the entire project.

For example, this means that, without altering the nr3 files, your project will have only one source file that includes nr3.h, and none of your included files will also include nr3.h. The most straightforward way to do this is to have a project that consists of a single source file.

Regards,

Dave

Footnote: If for some reason you can't create a directory as I showed in the second method, create it wherever you want to. Then you can put the absolute path to the nr3 files in the include statements. Note also that you don't have to use the horrible backslash rigmarole in path names; forward slashes work just fine.

orstats
11-03-2008, 09:52 PM
Hello: I did not see some of the drop-down features that you pointed to under Properties. I have however copied and pasted the libraries (nr3.h,incgammabeta.h,gamma.h) as new objects in the project. However, as I compile the main file I still get the error:

'gammln' identifier not found in the incgammabeta.h file.

:(

davekw7x
11-03-2008, 10:40 PM
...I still get the error:...'gammln' identifier not found in the incgammabeta.h file.

Did you include the necessary nr3 files in the correct order?


#include "nr3.h"
#include "gamma.h"
#Include "incgammabeta.h"


Did you get any other errors or any other compiler messages at all?

What does your source code look like now? Can you post it?

Don't post the nr3 routines, just show your cpp file where you include the nr3 files and where you use the functions therein. Give us something that we can compile.

Regards,

Dave

orstats
11-05-2008, 01:46 AM
The error that 'gammln' identifier not found was originating in the incgammabeta.h of the code. The main prgm now looks like the following:

#include "nr3.h"
#include "gamma.h"
#include "incgammabeta.h"
using namespace std;

int main()
{
double a, b, x, incompleteBeta;
a = 1.0;
b = 0.5;
x = 0.01;

Beta myBeta;
incompleteBeta = myBeta.betai(a, b, x);

cout << "I(" << x << ";"<< a << "," << b << ") = "
<< scientific << incompleteBeta
<< endl;

return 0;
}

And incgammabeta.h is the following:

struct Gauleg18 {
static const Int ngau = 18;
static const Doub y[18];
static const Doub w[18];
};
const Doub Gauleg18::y[18] = {0.0021695375159141994,
0.011413521097787704,0.027972308950302116,0.051727 015600492421,
0.082502225484340941, 0.12007019910960293,0.16415283300752470,
0.21442376986779355, 0.27051082840644336, 0.33199876341447887,
0.39843234186401943, 0.46931971407375483, 0.54413605556657973,
0.62232745288031077, 0.70331500465597174, 0.78649910768313447,
0.87126389619061517, 0.95698180152629142};
const Doub Gauleg18::w[18] = {0.0055657196642445571,
0.012915947284065419,0.020181515297735382,0.027298 621498568734,
0.034213810770299537,0.040875750923643261,0.047235 083490265582,
0.053244713977759692,0.058860144245324798,0.064039 797355015485,
0.068745323835736408,0.072941885005653087,0.076598 410645870640,
0.079687828912071670,0.082187266704339706,0.084078 218979661945,
0.085346685739338721,0.085983275670394821};
struct Gamma : Gauleg18 {
static const Int ASWITCH=100;
static const Doub EPS;
static const Doub FPMIN;
Doub gln;

Doub gammp(const Doub a, const Doub x) {
if (x < 0.0 || a <= 0.0) throw("bad args in gammp");
if (x == 0.0) return 0.0;
else if ((Int)a >= ASWITCH) return gammpapprox(a,x,1);
else if (x < a+1.0) return gser(a,x);
else return 1.0-gcf(a,x);
}

Doub gammq(const Doub a, const Doub x) {
if (x < 0.0 || a <= 0.0) throw("bad args in gammq");
if (x == 0.0) return 1.0;
else if ((Int)a >= ASWITCH) return gammpapprox(a,x,0);
else if (x < a+1.0) return 1.0-gser(a,x);
else return gcf(a,x);
}

Doub gser(const Doub a, const Doub x) {
Doub sum,del,ap;
gln=gammln(a);
ap=a;
del=sum=1.0/a;
for (;;) {
++ap;
del *= x/ap;
sum += del;
if (fabs(del) < fabs(sum)*EPS) {
return sum*exp(-x+a*log(x)-gln);
}
}
}

Doub gcf(const Doub a, const Doub x) {
Int i;
Doub an,b,c,d,del,h;
gln=gammln(a);
b=x+1.0-a;
c=1.0/FPMIN;
d=1.0/b;
h=d;
for (i=1;;i++) {
an = -i*(i-a);
b += 2.0;
d=an*d+b;
if (fabs(d) < FPMIN) d=FPMIN;
c=b+an/c;
if (fabs(c) < FPMIN) c=FPMIN;
d=1.0/d;
del=d*c;
h *= del;
if (fabs(del-1.0) <= EPS) break;
}
return exp(-x+a*log(x)-gln)*h;
}

Doub gammpapprox(Doub a, Doub x, Int psig) {
Int j;
Doub xu,t,sum,ans;
Doub a1 = a-1.0, lna1 = log(a1), sqrta1 = sqrt(a1);
gln = gammln(a);
.
.
.
};
:confused:

davekw7x
11-05-2008, 01:05 PM
The error...


I am going to try one more time.

Create a new directory. If your home drive is C:, then create C:\testmgln

Paste the following main program into a text editor window and save the file in that directory. Call the file xmgln.cpp


#include "./nr3.h"
#include "./gamma.h"
#include "./incgammabeta.h"
using namespace std;

int main()
{
double a, b, x, incompleteBeta;
a = 1.0;
b = 0.5;
x = 0.01;

Beta myBeta;
incompleteBeta = myBeta.betai(a, b, x);

cout << "I(" << x << ";" << a << "," << b << ") = "
<< scientific << incompleteBeta << endl;

return 0;
}



Copy nr3.h and gamma.h and incgammabeta.h from the NR3 code directory to C:\testmgln

Important: Use the files from the NR3 distribution! Do not alter them in any way!


From your start menu, look in ->Programs find the directory that was created when you installed Visual Studio 2008. In my installation, that directory is called "Visual C++ 9.0 Express Edition"

There is a "Visual Studio Tools" directory under that, and there is a icon named "Visual Studio 2008 Command Prompt"

Click the "Visual Studio 2008 Command Prompt" icon and a command window opens.

In the command window on my system, it gives the following prompt:

C:\Program Files\Microsoft Visual Studio 9.0\VC

Enter the following:


cd \testmgln
dir


You should see the four files that you just put into that directory.

Now, here's the biggie. Enter the following from the command line:


cl xmgln.cpp /EHsc


That's a lower-case L on the "cl" command. Enter it exactly as I showed. (Just paste it from this post, if possible.)

Here's what I see:

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

xmgln.cpp
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.

/out:xmgln.exe
xmgln.obj


Now when I do a "dir," I see that there are files named "xmgln.obj" and "xmgln.exe"

Enter the following on the command line:


xmgln


Here is what I see:


I(0.01;1,0.5) = 5.012563e-003




Regards,

Dave

orstats
11-09-2008, 04:05 AM
Dave: That absolutely worked! Thank you so much!! :) But from here, would I have to figure out how to run all my programs via the prompt? I am not sure why the same thing I couldn't get to execute properly using the IDE.

davekw7x
11-09-2008, 09:25 AM
Dave: That absolutely worked!...But from here...using the IDE.

Well, if it works, why not use it?

However, if somehow you are determined to use the IDE...

Here is a way. This works for me with the Microsoft Visual C++ 2008 Express Edition (the free download).

I am assuming that you have files xmglin.cpp and nr3.h and gamma.h and incgamma.h all in directory C:\testmgln




Create a new project in the directory where your files reside. From the File menu, click New->Project.


It will be a "Win32 Console Application. For the name, enter testmgln, and in the location enter C:\

The solution name will be testmgln. Uncheck the box that says "Create a Directory for the Application."


When you get to the "Application Settings" part of the project wizard, uncheck the "Precompiled header" box in the "Additional options" part.


After the project wizard is finished, there are some files in the solution: stdafx.h, targetver.h, stdafx.cpp, testmgln.cpp

Remove all of these from the project by right-clicking on each file and selecting "Exclude from project" from the context menu.


Add your files to the project. Right-click on the "Source Files" icon and select "Add Existing Item." Hold the Ctrl key down and click on gamma.h, incgammabeta.h, nr3.h, and xmgln.cpp. Then click the "Add" button.


From the Build menu, click "Build Solution"


The project will build xmgln.exe and it will be in directory C:\testmgln\Debug (You can check it from a command line by executing dir c:\testmgln\Debug. There will be other files there as well, and a number of new files in c:\testmgln


From the IDE, select Start without debugging from the Debug menu. The IDE will open a command prompt window and show the program output. A message "Press any key to continue . . . " appears. Press 'Enter' and the command prompt window goes away and control returns to the IDE


Note that if you select Start with debugging from the Debug menu, the IDE opens a command prompt window, executes the program and then closes the window. (Undoubtedly this will happen so fast that you can't see the output.) To keep this from happening, you can add two lines at the bottom of xmgln.cpp to make the IDE command prompt window stay open until you hit the 'Enter' key.




{
.
.
.
cout << "I(" << x << ";" << a << "," << b << ") = "
<< scientific << incompleteBeta << endl;

cout << "Press Enter to exit the program . . . ";
cin.get();

return 0;
}


Now you can run from the IDE in either mode. I always run command line programs from the command line, so I don't need the extra lines. I also always compile command line programs from the command line, so I just about never use the IDE except for Windows programs.

I mean, why the heck would I go through all of the above steps when I can just execute "cl xmgln.cpp /EHsc" from the command line, and then execute the program by entering "xmgln". No worries about having to put extra stuff in the program to prevent a window opening and closing in a flash, etc.

Oh, well...

Regards,

Dave

orstats
11-09-2008, 02:18 PM
Yep, well said. I have been trying to construct the automatic link to MATLAB from Visual Studio 2008 professional using the guide

http://www.nr.com/nr3_matlab.html#msvs
But I keep running into the compilation error

http://www.nr.com/forum/showthread.php?t=1391

And I just wonder if I can execute the same thing via the Command Prompt.