I was trying to integrate this function:
proc int2gf(x); retp( (x^2 .* dlnm(x,muf,sigmaf)) ); endp;
over 5 to ∞.
I was looking the help about inthp, inthp2, but I don´t understand about the DS structure, the pds, and the inthpControl (what happens with ctl.p, ctl.d, etc? How can I use the different options?
We will work through this problem and give a working example. Let's start with the DS structure.
What is the DS structure?
The DS structure is a predefined GAUSS structure that contains a different member for each data type in GAUSS. The purpose of the DS structure is to give the user a package that can be filled with whatever the user's procedure requires and be easily passed. This allows a GAUSS function like inthp2 to hand your function any number of variables and data types without knowing what they will be. This will become more clear as we work through an example.
How do I use a DS structure?
The steps to use a DS structure are to:
- Declare the structure instance
- Fill in the structure with default values
- Optionally, reshape the structure into an array of structures
- Add your data to the structure
Here is an example of the steps above:
//Declare 'mydata' to be an instance of a DS structure struct DS mydata; //Fill in the structure instance, 'mydata', with default values mydata = dsCreate(); //Reshape the data into a 2x1 array of structures mydata = reshape(mydata, 2, 1); //Create two variables that we would like to add //to our DS structure array muf = 4.7; sigma = 1.3; //The 'dataMatrix' member of the 'DS' structure is //a matrix to which you can add any data //Here we add the value of 'muf' to the //'dataMatrix' member of the first element //of our 2x1 array of structures mydata.dataMatrix = muf; //Assign the 'dataMatrix' member of the second //struct in the array to be equal to the value //of sigma mydata.dataMatrix = sigma;
Now we have a structure named mydata that contains both of the scalars, muf and sigma. In this case, it might not seem so helpful to set this up just to pass around two scalars. However, with this technique you could pass any combination of dense matrices, sparse matrices, n-dimensional arrays and scalars with only an extra line or two of code added to the above.
Creating a structure pointer from a structure
The documentation for the function inthp2 requires a pointer to the DS structure. A pointer to a structure is essentially just a scalar value that tells GAUSS where to find the actual structure when it is needed. This is much more efficient, because now GAUSS only needs to pass this tiny value around instead of a possibly large structure.
There are two steps to use a structure pointer:
- Declare the structure pointer
- Assign the structure pointer
Continuing with the code from above, we will create and assign a structure pointer that points to the mydata structure instance.
//Declare structure pointer //Note the * in front of the variable name struct DS *p_mydata; //Assign 'p_mydata' to point at 'mydata' //Note the & in front of 'mydata' p_mydata = &mydata;
Setting up a function to take a pointer to a DS structure
The function that we are going to integrate needs to take a pointer to a DS structure as well as the integration variable x. We can transform your function to take a pointer to a DS structure like this:
proc (1) = int2gf(struct DS *extra_data, x); local muf_l, sigma_l, out; //Extract the variables from the DS structure //Note that structure pointers use -> //to reference their members rather than //the . operator muf_l = extra_data->dataMatrix; sigma_l = extra_data->dataMatrix; //Pass the variables taken from the DS structure //pointer to the 'dlnm' function out = x .* dlnm(x, muf_l, sigma_l) retp(out); endp; //I created a procedure named 'dlnm' to create //a fully functioning example proc (1) = dlnm(x, muf, sigma); retp(1/(x .* (x + muf) .* sqrt(x) .* sigma )); endp;
Setting up the Inthp control structure
The inthpControl structure is used in the same manner as the DS structure, like this:
//Declare structure instance struct inthpControl ctl; //Fill in with default values ctl = inthpControlCreate();
Any of the default settings can be changed by using the dot (.) operator like this:
ctl.eps = 1e-5; ctl.p = 2;
Final step, calling 'inthp2'
Using the variables created above, we can call inthp with the following line of code:
//Note the & in front of the function name //This is because we are passing a pointer //to the function. //We do not need an & in front of 'p_mydata' //because it IS a pointer already area = inthp2(&int2gf, p_mydata, ctl, 5);
After working through all of that, below is a self-contained, working example. It is slightly different than what was worked through above. The difference is that it does not reshape the DS structure. It simply assigns the first and second elements of the dataMatrix member to hold the muf and sigma variables.
new; //Declare and instantiate DS structure struct DS mydata; mydata = dsCreate(); //Instantiate 'muf' and 'sigma' muf = 4.7; sigma = 1.3; //Add variables 'muf' and 'sigma' to DS structure mydata.dataMatrix = muf|sigma; //Create pointer to mydata structure struct DS *p_mydata; p_mydata = &mydata; struct inthpControl ctl; ctl = inthpControlCreate(); inthp2(&int2gf, p_mydata, ctl, 5); proc (1) = int2gf(struct DS *extra_data, x); local muf_l, sigma_l; muf_l = extra_data->dataMatrix; sigma_l = extra_data->dataMatrix; retp(x .* dlnm(x, muf_l, sigma_l)); endp; proc (1) = dlnm(x, muf, sigma); retp(1/(x .* (x + muf) .* sqrt(x) .* sigma )); endp;