MATLAB Newsgroup

I am creating a gateway function to a C file which uses the long integer type. I cannot change the type in the C file.

The C file takes all of it's arguments as pointers (it is actually a conversion from a Fortran program created with the utility 'f2c').

I would like to ensure cross-platform compatibility of the routine. What is the best way to ensure that I am passing a type long int into my computation routine, taking account of the local processor architecture?

My gateway function is shown below (with some error checking code stripped out):

/* the gateway function */

void mexFunction( int nlhs, mxArray *plhs[],

int nrhs, const mxArray *prhs[])

{

double *W, *PRGOPT, *WS, *IP;

int *MDW, *ME, *MA, *MG, *N;

double *X, *RNORME, *RNORML;

int *MODE;

mwSize matm, matn;

/* create a pointer to the input vector W */

W = mxGetPr(prhs[0]);

/* get the scalar input MDW */

MDW = mxGetPr(prhs[1]);

/* get the scalar input ME */

ME = mxGetPr(prhs[2]);

/* get the scalar input MA */

MA = mxGetPr(prhs[3]);

/* get the scalar input MG */

MG = mxGetPr(prhs[4]);

/* get the scalar input N */

N = mxGetPr(prhs[5]);

/* get the vector input PRGOPT */

PRGOPT = mxGetPr(prhs[6]);

/* get the vector input/output X */

X = mxGetPr(prhs[7]);

/* get the scalar input RNORME */

RNORME = mxGetPr(prhs[8]);

/* get the scalar input RNORML */

RNORML = mxGetPr(prhs[9]);

/* get the scalar input MODE */

MODE = mxGetPr(prhs[10]);

/* get the vector input WS */

WS = mxGetPr(prhs[11]);

/* get the vector input IP */

IP = mxGetPr(prhs[12]);

/* set the output pointer to the output matrix */

//plhs[0] = mxCreateDoubleMatrix(mrows,ncols, mxREAL);

/* set the output pointers to the output matrices */

/* call the C subroutine */

dlsei_(W, MDW, ME, MA, MG, N, PRGOPT, X, RNORME, RNORML, MODE, WS, IP);

plhs[0] = mxDuplicateArray(prhs[7]);

plhs[1] = mxDuplicateArray(prhs[8]);

plhs[2] = mxDuplicateArray(prhs[9]);

plhs[3] = mxDuplicateArray(prhs[10]);

}

Basically, how do I ensure that whatever I pass in from Matlab becomes a long int before being passed to dlsei_? Or alternatively, ensure that a long int is always 32 bits or something like this.

Thanks

"Richard Crozier" wrote in message <iie4hv$f3n$1@fred.mathworks.com>...

> I am creating a gateway function to a C file which uses the long integer type. I cannot change the type in the C file.

>

> The C file takes all of it's arguments as pointers (it is actually a conversion from a Fortran program created with the utility 'f2c').

>

> I would like to ensure cross-platform compatibility of the routine. What is the best way to ensure that I am passing a type long int into my computation routine, taking account of the local processor architecture?

>

> My gateway function is shown below (with some error checking code stripped out):

>

> /* the gateway function */

> void mexFunction( int nlhs, mxArray *plhs[],

> int nrhs, const mxArray *prhs[])

> {

> double *W, *PRGOPT, *WS, *IP;

> int *MDW, *ME, *MA, *MG, *N;

> double *X, *RNORME, *RNORML;

> int *MODE;

> mwSize matm, matn;

>

> /* create a pointer to the input vector W */

> W = mxGetPr(prhs[0]);

>

> /* get the scalar input MDW */

> MDW = mxGetPr(prhs[1]);

>

> /* get the scalar input ME */

> ME = mxGetPr(prhs[2]);

>

> /* get the scalar input MA */

> MA = mxGetPr(prhs[3]);

>

> /* get the scalar input MG */

> MG = mxGetPr(prhs[4]);

>

> /* get the scalar input N */

> N = mxGetPr(prhs[5]);

>

> /* get the vector input PRGOPT */

> PRGOPT = mxGetPr(prhs[6]);

>

> /* get the vector input/output X */

> X = mxGetPr(prhs[7]);

>

> /* get the scalar input RNORME */

> RNORME = mxGetPr(prhs[8]);

>

> /* get the scalar input RNORML */

> RNORML = mxGetPr(prhs[9]);

>

> /* get the scalar input MODE */

> MODE = mxGetPr(prhs[10]);

>

> /* get the vector input WS */

> WS = mxGetPr(prhs[11]);

>

> /* get the vector input IP */

> IP = mxGetPr(prhs[12]);

>

> /* set the output pointer to the output matrix */

> //plhs[0] = mxCreateDoubleMatrix(mrows,ncols, mxREAL);

> /* set the output pointers to the output matrices */

>

> /* call the C subroutine */

> dlsei_(W, MDW, ME, MA, MG, N, PRGOPT, X, RNORME, RNORML, MODE, WS, IP);

>

> plhs[0] = mxDuplicateArray(prhs[7]);

> plhs[1] = mxDuplicateArray(prhs[8]);

> plhs[2] = mxDuplicateArray(prhs[9]);

> plhs[3] = mxDuplicateArray(prhs[10]);

>

> }

>

> Basically, how do I ensure that whatever I pass in from Matlab becomes a long int before being passed to dlsei_? Or alternatively, ensure that a long int is always 32 bits or something like this.

>

> Thanks

The easiest thing to do is to check the sizeof(long int), see how many bits it is, and then use that type on the MATLAB side for all of your mex argument inputs (e.g., int32). You can always but a check in your mex routine to make sure that the inputs are the correct bitlength for the dlsei_ routine or throw an error.

The harder way is to convert all of your inputs inside the mex routine to the correct type, then pass *them* to the dlsei_ routine.

Q: If your dlsei_ routine is using long int, why are you using int above instead of long int?

You may have a problem with this line:

> /* get the vector input/output X */

> X = mxGetPr(prhs[7]);

as it appears you are using the prhs[7] variable as both input/output to the routine. So I am guessing that dlsei_ changes X inplace? Then you later copy the results to the output here:

> plhs[0] = mxDuplicateArray(prhs[7]);

This will change the input argument on the MATLAB side, which I don't think you want. You need to copy the input *first*, and then pass the copy to the dlsei_ routine.

Also, if all of your long int arguments are scalars, you are going about this the hard way. Just declare them as long int (not pointers) and then pass their addresses to dlsei_. e.g., instead of doing this for MDW:

> int *MDW;

:

> /* get the scalar input MDW */

> MDW = mxGetPr(prhs[1]);

:

> /* call the C subroutine */

> dlsei_(W, MDW, ME, MA, MG, N, PRGOPT, X, RNORME, RNORML, MODE, WS, IP);

it is easier to do this:

long MDW;

:

/* get the scalar input MDW */

MDW = mxGetScalar(prhs[1]);

:

/* call the C subroutine */

dlsei_(W, &MDW, ME, MA, MG, N, PRGOPT, X, RNORME, RNORML, MODE, WS, IP);

And, of course, do the same thing for all of your other scalar long int inputs (not shown above).

James Tursa

"James Tursa" wrote in message <iiek4m$snu$1@fred.mathworks.com>...

> "Richard Crozier" wrote in message <iie4hv$f3n$1@fred.mathworks.com>...

> > I am creating a gateway function to a C file which uses the long integer type. I cannot...

snip

> > Thanks

>

> The easiest thing to do is to check the sizeof(long int), see how many bits it is, and then use that type on the MATLAB side for all of your mex argument inputs (e.g., int32). You can always but a check in your mex routine to make sure that the inputs are the correct bitlength for the dlsei_ routine or throw an error.

>

> The harder way is to convert all of your inputs inside the mex routine to the correct type, then pass *them* to the dlsei_ routine.

>

> Q: If your dlsei_ routine is using long int, why are you using int above instead of long int?

>

> You may have a problem with this line:

>

> > /* get the vector input/output X */

> > X = mxGetPr(prhs[7]);

>

> as it appears you are using the prhs[7] variable as both input/output to the routine. So I am guessing that dlsei_ changes X inplace? Then you later copy the results to the output here:

>

> > plhs[0] = mxDuplicateArray(prhs[7]);

>

> This will change the input argument on the MATLAB side, which I don't think you want. You need to copy the input *first*, and then pass the copy to the dlsei_ routine.

>

> Also, if all of your long int arguments are scalars, you are going about this the hard way. Just declare them as long int (not pointers) and then pass their addresses to dlsei_. e.g., instead of doing this for MDW:

>

> > int *MDW;

> :

> > /* get the scalar input MDW */

> > MDW = mxGetPr(prhs[1]);

> :

> > /* call the C subroutine */

> > dlsei_(W, MDW, ME, MA, MG, N, PRGOPT, X, RNORME, RNORML, MODE, WS, IP);

>

> it is easier to do this:

>

> long MDW;

> :

> /* get the scalar input MDW */

> MDW = mxGetScalar(prhs[1]);

> :

> /* call the C subroutine */

> dlsei_(W, &MDW, ME, MA, MG, N, PRGOPT, X, RNORME, RNORML, MODE, WS, IP);

>

> And, of course, do the same thing for all of your other scalar long int inputs (not shown above).

>

>

> James Tursa

Hi James, thanks for replying.

To answer you first question, that was just a mistake on my part, they should all be the long int type.

To reply to your more general comment about the variables being manipulated 'in place' this is indded the case, but this is dictated by the subroutine dlsei__. This routing was created from fortran source files via the conversion program f2c. In the original fortran program it is necesary to create arrays of the correct length for the output.

The variables W, PRGOPT, IP, MDW, ME, MA, MG, N ans IP are the real inputs

The variables X, RNORME, RNORML and MODE are the real outputs

The variables IP and WS are arrays used as workspace in dlsei__ and must be preallocated a certain minimum size based on the values on ME, MA, and N etc.

I'm not that hot on C programming and it is much simpler for me to preallocate all these variables in matlab to the correct sizes and pass these in.

I want also want to work on various machine architectures, including at least win32 and glnxa64 (64 bit linux). On my windowx XP machine a long int is 32 bits, on the linux machine a long int is 64 bits. I also have a 64 bit windows Vista machine I also want to work, I haven't tested the long int size on this yet. Matlab does not provide a command to get the size of a long int on the local machine, and this would probably be compiler specific anyway (correct me if I'm wrong though!).

So, based on this and your initial advice, I now have the following code

/* the gateway function */

void mexFunction( int nlhs, mxArray *plhs[],

int nrhs, const mxArray *prhs[])

{

double *W, *PRGOPT, *WS, *IP;

long MDW, ME, MA, MG, N, MODE;

double *X, *RNORME, *RNORML;

double *MODEOUT;

mwSize matm, matn;

/*

printf("long int size: %zu", sizeof(long));

*/

/* set the output pointers to the output matrices */

plhs[0] = mxDuplicateArray(prhs[7]);

plhs[1] = mxDuplicateArray(prhs[8]);

plhs[2] = mxDuplicateArray(prhs[9]);

/* create a pointer to the input vector W */

W = mxGetPr(prhs[0]);

/* get the scalar input MDW */

MDW = (long) mxGetScalar(prhs[1]);

/* get the scalar input ME */

ME = (long) mxGetScalar(prhs[2]);

/* get the scalar input MA */

MA = (long) mxGetScalar(prhs[3]);

/* get the scalar input MG */

MG = (long) mxGetScalar(prhs[4]);

/* get the scalar input N */

N = (long) mxGetScalar(prhs[5]);

/* get the vector input PRGOPT */

PRGOPT = mxGetPr(prhs[6]);

/* get the vector input/output X */

X = mxGetPr(plhs[0]);

/* get the scalar input RNORME */

RNORME = mxGetPr(plhs[1]);

/* get the scalar input RNORML */

RNORML = mxGetPr(plhs[2]);

/* get the scalar input MODE */

MODE = (long) mxGetScalar(prhs[10]);

/* get the vector input WS */

WS = mxGetPr(prhs[11]);

/* get the vector input IP */

IP = mxGetPr(prhs[12]);

plhs[3] = mxCreateDoubleMatrix(1, 1, mxREAL);

MODEOUT = mxGetPr(plhs[3]);

/* call the C subroutine */

dlsei_(W, &MDW, &ME, &MA, &MG, &N, PRGOPT, X, RNORME, RNORML, &MODE, WS, IP);

*MODEOUT = (double) MODE;

}

This does seem to work, but is there a better way to handle the X, RNORME and RNORML variables? RNORME and RNORML are always scalar doubles, X is an array of N doubles, i.e.they are created in the matlab calling function by:

rnorml = 0;

rnorme = 0;

x = zeros(N,1);

And will never have anything but zeros in them before being sent to dlsei__

Anyway, don't worry if you don't have time to answer this either, it's quite a long one! Thanks for your help so far anyway.

"Richard Crozier" wrote in message <iigrvc$im5$1@fred.mathworks.com>...

> "James Tursa" wrote in message <iiek4m$snu$1@fred.mathworks.com>...

> > "Richard Crozier" wrote in message <iie4hv$f3n$1@fred.mathworks.com>...

Oh, and please excuse the many typos in the last message. It was typed on a remote connection that renders by mouse cursor invisible, and doesn't allow the use of the arrow keys, or the DEL key!

"Richard Crozier" wrote in message <iigrvc$im5$1@fred.mathworks.com>...

>

> To reply to your more general comment about the variables being manipulated 'in place' this is indded the case, but this is dictated by the subroutine dlsei__. This routing was created from fortran source files via the conversion program f2c. In the original fortran program it is necesary to create arrays of the correct length for the output.

>

> The variables W, PRGOPT, IP, MDW, ME, MA, MG, N ans IP are the real inputs

>

> The variables X, RNORME, RNORML and MODE are the real outputs

>

> The variables IP and WS are arrays used as workspace in dlsei__ and must be preallocated a certain minimum size based on the values on ME, MA, and N etc.

>

> I'm not that hot on C programming and it is much simpler for me to preallocate all these variables in matlab to the correct sizes and pass these in.

>

> I want also want to work on various machine architectures, including at least win32 and glnxa64 (64 bit linux). On my windowx XP machine a long int is 32 bits, on the linux machine a long int is 64 bits. I also have a 64 bit windows Vista machine I also want to work, I haven't tested the long int size on this yet. Matlab does not provide a command to get the size of a long int on the local machine, and this would probably be compiler specific anyway (correct me if I'm wrong though!).

>

> So, based on this and your initial advice, I now have the following code

>

> /* the gateway function */

> void mexFunction( int nlhs, mxArray *plhs[],

> int nrhs, const mxArray *prhs[])

> {

> double *W, *PRGOPT, *WS, *IP;

> long MDW, ME, MA, MG, N, MODE;

> double *X, *RNORME, *RNORML;

> double *MODEOUT;

> mwSize matm, matn;

>

> /*

> printf("long int size: %zu", sizeof(long));

> */

> /* set the output pointers to the output matrices */

> plhs[0] = mxDuplicateArray(prhs[7]);

> plhs[1] = mxDuplicateArray(prhs[8]);

> plhs[2] = mxDuplicateArray(prhs[9]);

>

> /* create a pointer to the input vector W */

> W = mxGetPr(prhs[0]);

>

> /* get the scalar input MDW */

> MDW = (long) mxGetScalar(prhs[1]);

>

> /* get the scalar input ME */

> ME = (long) mxGetScalar(prhs[2]);

>

> /* get the scalar input MA */

> MA = (long) mxGetScalar(prhs[3]);

>

> /* get the scalar input MG */

> MG = (long) mxGetScalar(prhs[4]);

>

> /* get the scalar input N */

> N = (long) mxGetScalar(prhs[5]);

>

> /* get the vector input PRGOPT */

> PRGOPT = mxGetPr(prhs[6]);

>

> /* get the vector input/output X */

> X = mxGetPr(plhs[0]);

>

> /* get the scalar input RNORME */

> RNORME = mxGetPr(plhs[1]);

>

> /* get the scalar input RNORML */

> RNORML = mxGetPr(plhs[2]);

>

> /* get the scalar input MODE */

> MODE = (long) mxGetScalar(prhs[10]);

>

> /* get the vector input WS */

> WS = mxGetPr(prhs[11]);

>

> /* get the vector input IP */

> IP = mxGetPr(prhs[12]);

>

> plhs[3] = mxCreateDoubleMatrix(1, 1, mxREAL);

>

> MODEOUT = mxGetPr(plhs[3]);

>

> /* call the C subroutine */

> dlsei_(W, &MDW, &ME, &MA, &MG, &N, PRGOPT, X, RNORME, RNORML, &MODE, WS, IP);

>

> *MODEOUT = (double) MODE;

>

> }

>

> This does seem to work, but is there a better way to handle the X, RNORME and RNORML variables? RNORME and RNORML are always scalar doubles, X is an array of N doubles, i.e.they are created in the matlab calling function by:

>

> rnorml = 0;

> rnorme = 0;

> x = zeros(N,1);

>

> And will never have anything but zeros in them before being sent to dlsei__

>

> Anyway, don't worry if you don't have time to answer this either, it's quite a long one! Thanks for your help so far anyway.

This method is basically a waste of time and resources:

> */

> /* set the output pointers to the output matrices */

> plhs[0] = mxDuplicateArray(prhs[7]);

> plhs[1] = mxDuplicateArray(prhs[8]);

> plhs[2] = mxDuplicateArray(prhs[9]);

You apparently are creating the inputs to the mex routine for the sole purpose of duplicating them inside the mex routine to get the output variables to use. If N is small then no big deal ... you will never notice the waste. But if N is large then you may get some impacts. But aside from that, the whole interface would be confusing to another person quite frankly ... most people would expect m-files and mex files to create the outputs they need themselves rather than relying on correctly sized inputs for this. My advice on a better approach is to create the output arrays inside the mex routine itself. e.g., like this:

plhs[0] = mxCreateDoubleMatrix(N,1,mxREAL); // be sure you define N first

plhs[1] = mxCreateDoubleScalar(0.0);

plhs[2] = mxCreateDoubleScalar(0.0);

X = mxGetPr(plhs[0]);

RNORME = mxGetPr(plhs[1]);

RNORML = mxGetPr(plhs[2]);

And at the end, you could replace this code:

> plhs[3] = mxCreateDoubleMatrix(1, 1, mxREAL);

>

> MODEOUT = mxGetPr(plhs[3]);

>

> /* call the C subroutine */

> dlsei_(W, &MDW, &ME, &MA, &MG, &N, PRGOPT, X, RNORME, RNORML, &MODE, WS, IP);

>

> *MODEOUT = (double) MODE;

with this instead (a bit simpler for plhs[3]):

> /* call the C subroutine */

> dlsei_(W, &MDW, &ME, &MA, &MG, &N, PRGOPT, X, RNORME, RNORML, &MODE, WS, IP);

>

> plhs[3] = mxCreateDoubleScalar(MODE);

James Tursa

You can think of your watch list as threads that you have bookmarked.

You can add tags, authors, threads, and even search results to your watch list. This way you can easily keep track of topics that you're interested in. To view your watch list, click on the "My Newsreader" link.

To add items to your watch list, click the "add to watch list" link at the bottom of any page.

To add search criteria to your watch list, search for the desired term in the search box. Click on the "Add this search to my watch list" link on the search results page.

You can also add a tag to your watch list by searching for the tag with the directive "tag:tag_name" where tag_name is the name of the tag you would like to watch.

To add an author to your watch list, go to the author's profile page and click on the "Add this author to my watch list" link at the top of the page. You can also add an author to your watch list by going to a thread that the author has posted to and clicking on the "Add this author to my watch list" link. You will be notified whenever the author makes a post.

To add a thread to your watch list, go to the thread page and click the "Add this thread to my watch list" link at the top of the page.

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

The newsgroups are a worldwide forum that is open to everyone. Newsgroups are used to discuss a huge range of topics, make announcements, and trade files.

Discussions are threaded, or grouped in a way that allows you to read a posted message and all of its replies in chronological order. This makes it easy to follow the thread of the conversation, and to see what’s already been said before you post your own reply or make a new posting.

Newsgroup content is distributed by servers hosted by various organizations on the Internet. Messages are exchanged and managed using open-standard protocols. No single entity “owns” the newsgroups.

There are thousands of newsgroups, each addressing a single topic or area of interest. The MATLAB Central Newsreader posts and displays messages in the comp.soft-sys.matlab newsgroup.

**MATLAB Central**

You can use the integrated newsreader at the MATLAB Central website to read and post messages in this newsgroup. MATLAB Central is hosted by MathWorks.

Messages posted through the MATLAB Central Newsreader are seen by everyone using the newsgroups, regardless of how they access the newsgroups. There are several advantages to using MATLAB Central.

**One Account**

Your MATLAB Central account is tied to your MathWorks Account for easy access.

**Use the Email Address of Your Choice**

The MATLAB Central Newsreader allows you to define an alternative email address as your posting address, avoiding clutter in your primary mailbox and reducing spam.

**Spam Control**

Most newsgroup spam is filtered out by the MATLAB Central Newsreader.

**Tagging**

Messages can be tagged with a relevant label by any signed-in user. Tags can be used as keywords to find particular files of interest, or as a way to categorize your bookmarked postings. You may choose to allow others to view your tags, and you can view or search others’ tags as well as those of the community at large. Tagging provides a way to see both the big trends and the smaller, more obscure ideas and applications.

**Watch lists**

Setting up watch lists allows you to be notified of updates made to postings selected by author, thread, or any search variable. Your watch list notifications can be sent by email (daily digest or immediate), displayed in My Newsreader, or sent via RSS feed.

- Use a newsreader through your school, employer, or internet service provider
- Pay for newsgroup access from a commercial provider
- Use Google Groups
- Mathforum.org provides a newsreader with access to the comp.soft sys.matlab newsgroup
- Run your own server. For typical instructions, see: http://www.slyck.com/ng.php?page=2