Thread Subject: Boolean variables in a MEX file

Subject: Boolean variables in a MEX file

From: evansstev@yahoo.com

Date: 9 Nov, 2007 21:32:49

Message: 1 of 4

I wrote a simple MEX file that SHOULD work, but it doesn't. The
following is the contents of the MEX file. The source MEX file is
called "cpptest.cpp".


#include "mex.h"
#include "matrix.h"
#include <string.h>

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])
{
    const int dims[]={1,5};
    bool *V;
    V = mxGetLogicals(prhs[0]);

    *(V+4) = *(V+0)||*(V+1)||*(V+2)||*(V+3);

    plhs[0] = mxCreateLogicalArray(2,dims);
    memcpy(mxGetLogicals(plhs[0]),V,5*mxGetElementSize(plhs[0]));
}


When running the resulting function for this MEX file, I should get
the following result:


y = cpptest([1 0 1 0 0])

y =
1 0 1 0 1


However, I get this instead:


y = cpptest([1 0 1 0 0])

y =
0 0 0 0 0

Does anyone have any idea why this function produces all zeros every
time? I have been able to get this MEX file to work if I let the
class type be "double" instead of "bool", or "Logical". However,
because the values that are being worked with, will always be ones and
zeros, "bool" is a much more efficent class to use. Here's what the
MEX file looks like if I let the class be of type "double":


#include "mex.h"
#include "matrix.h"
#include <string.h>

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])
{
    int mrows, ncols;
    double *V;
    V = mxGetPr(prhs[0]);

    *(V+4) = *(V+0)||*(V+1)||*(V+2)||*(V+3);

    mrows = mxGetM(prhs[0]);
    ncols = mxGetN(prhs[0]);
    plhs[0] = mxCreateDoubleMatrix(mrows,ncols, mxREAL);
    memcpy(mxGetPr(plhs[0]),V,5*mxGetElementSize(plhs[0]));
}


This MEX file is very similar to the boolean version, and it works.
It produces the expected result, but the values in the array are type
double. This takes up a lot more memory, and will probably run
slower. Does anyone know what I'm doing wrong with the boolean
version? Why does it always produce all zeros? How can I fix it?

Thanks for your time,

                                           Steven Evans

Subject: Boolean variables in a MEX file

From: Chris Hulbert

Date: 10 Nov, 2007 00:48:50

Message: 2 of 4

On Nov 9, 4:32 pm, evanss...@yahoo.com wrote:
> I wrote a simple MEX file that SHOULD work, but it doesn't. The
> following is the contents of the MEX file. The source MEX file is
> called "cpptest.cpp".
>
> #include "mex.h"
> #include "matrix.h"
> #include <string.h>
>
> void mexFunction(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])
> {
> const int dims[]={1,5};
> bool *V;
> V = mxGetLogicals(prhs[0]);
>
> *(V+4) = *(V+0)||*(V+1)||*(V+2)||*(V+3);
>
> plhs[0] = mxCreateLogicalArray(2,dims);
> memcpy(mxGetLogicals(plhs[0]),V,5*mxGetElementSize(plhs[0]));
>
> }
>
> When running the resulting function for this MEX file, I should get
> the following result:
>
> y = cpptest([1 0 1 0 0])
>
> y =
> 1 0 1 0 1
>
> However, I get this instead:
>
> y = cpptest([1 0 1 0 0])
>
> y =
> 0 0 0 0 0
>
> Does anyone have any idea why this function produces all zeros every
> time? I have been able to get this MEX file to work if I let the
> class type be "double" instead of "bool", or "Logical". However,
> because the values that are being worked with, will always be ones and
> zeros, "bool" is a much more efficent class to use. Here's what the
> MEX file looks like if I let the class be of type "double":
>
> #include "mex.h"
> #include "matrix.h"
> #include <string.h>
>
> void mexFunction(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])
> {
> int mrows, ncols;
> double *V;
> V = mxGetPr(prhs[0]);
>
> *(V+4) = *(V+0)||*(V+1)||*(V+2)||*(V+3);
>
> mrows = mxGetM(prhs[0]);
> ncols = mxGetN(prhs[0]);
> plhs[0] = mxCreateDoubleMatrix(mrows,ncols, mxREAL);
> memcpy(mxGetPr(plhs[0]),V,5*mxGetElementSize(plhs[0]));
>
> }
>
> This MEX file is very similar to the boolean version, and it works.
> It produces the expected result, but the values in the array are type
> double. This takes up a lot more memory, and will probably run
> slower. Does anyone know what I'm doing wrong with the boolean
> version? Why does it always produce all zeros? How can I fix it?


What is the type of [1 0 1 0 0]? It's a double which is why it works
with double. You should always check the input data type. You can try
logical([1 0 1 0 0]) as the input. Also, note that you assign data to
V[4], thus updating the input. This can have unintended and dangerous
consequences if the data is shared amongst variables. I would suggest
doing the memcpy first and then letting V = mxGetData(plhs[0]).

Chris

>
> Thanks for your time,
>
> Steven Evans

Subject: Boolean variables in a MEX file

From: James Tursa

Date: 10 Nov, 2007 10:03:56

Message: 3 of 4


As Chris already said, it is not clear that you actually want a mex
file that handles mxLogical data as input. Maybe your data is 0's and
1's but it is always double class. But taking you at your word, here
are some comments about your code:

(Chris has already noted the first two. I simply repeat them here)

1) You have made no checks for proper input type, size, etc. This can
cause nasty problems with memory if you don't pass the function
exactly what the code expects. Always check the input. For example, if
you pass in a double class variable, then you have passed in 8*5 = 40
bytes of data (plus the overhead stuff), but this line

> memcpy(mxGetLogicals(plhs[0]),V,5*mxGetElementSize(plhs[0]));

only copies 5*1 = 5 bytes of data. In fact, if the first element of
the double vector you passed in is 0 (such as your example), then the
data area of prhs[0] will start with eight bytes of exactly 0, the
first four of which you used for your logical calculations. You will
always get five zeros for your result in this case. Things would have
gotten really nasty here had you used prhs[0] for any memory copying
in a statement like this. For example, consider a similar statement:

    memcpy(mxGetLogicals(plhs[0]),V,5*mxGetElementSize(prhs[0]));

I only changed the argument of mxGetElementSize to use prhs[0] instead
of plhs[0]. This would cause 40 bytes to be written to a data area
only capable of holding 5 bytes, probably resulting in a MATLAB crash.

2) You change the actual memory of the input variable. This should
*never* be done. You have actually changed the value of the input
variable (bad enough), but may *also* have inadvertantly changed the
value of a completely different variable in the MATLAB workspace (one
that isn't even involved in the argument list) because it may have
shared memory with the input variable you are using. This is very bad,
so never do this.

3) You are assuming that an mxLogical is the same thing as a bool in
c. This is not a safe thing to do in general. mxLogical may be a bool
on some systems, but it may be something else (e.g., unsigned char) on
other systems. Since MATLAB uses 1 byte for a logical element in the
MATLAB workspace, they will probably always define mxLogical to be
something that is guaranteed to be 1 byte on the system it is
installed. For c in general the only thing you can count on is that a
char (or unsigned char) is 1 byte. You can't count on anything else.
You can't be sure how many bytes a short is, an int is, a long is, etc
etc. And you can't be sure how many bytes a bool is either. Unless you
know a lot about the system you will be running on ahead of time, the
only data length you can count on is char and unsigned char being 1
byte. A lot of systems (most?) these days define a bool to be 1 byte,
but strictly speaking this is processor dependent. So ... I advise
against using bool in your code. Use mxLogical, since MATLAB has
supplied that data type for you to use.

4) When using mxLogicals there is the problem that you don't know
exactly what it is (or will be if your code gets used on another
system). Will the underlying type be a bool? An unsigned char? So this
will have to be kept in mind when working with them in your code and
dereferencing them. I chose to use the bitwise operator | instead of
the logical operator || so that there wouldn't be any inadvertant type
conversions going on with this section of code:

> *(V+4) = *(V+0)||*(V+1)||*(V+2)||*(V+3);

The way you have it written, if the underlying type is unsigned char,
then the result of the logical operations will be a bool, and then the
final bool result will be cast back into an unsigned char. It would
not be obvious to a casual reader that there was type conversions
going on behind the scenes here. By rewriting it like this:

    *(V+4) = *(V+0) | *(V+1) | *(V+2) | *(V+3);

the bitwise operator keeps all of the intermediate and final result
types the same throughout the operations, regardless of what mxLogical
may really be. There are no hidden type conversions going on behind
the scenes.

The other advantage of using | is that the underlying bits of an
mxLogical true value are kept intact, regardless of what they might
be. As it happens, MATLAB uses the value 1 for logic true and so does
c for a bool value true, so there would not have been a problem here
using ||. But a similar construct like this in a Fortran mex file
would be a problem since logical true values can be -1 in Fortran,(all
bits set for a twos complement integer). (I mostly make this point for
other readers who might be Fortran mex programmers.)

5) When you are returning an mxArray of exactly the same class & size
etc. as an input mxArray, I find it convenient to use the
mxDuplicateArray function rather than getting the sizes, creating the
dims array, calling the mxCreate... etc function. Then I modify the
data in the new duplicate mxArray. The resulting code is often
simpler. mxDuplicateArray makes a deep copy, so you are assured that
there will be no shared data with the original.

Below I have included a version of your code that I have rewritten
according to my comments.

James Tursa



#include "mex.h"
#include "matrix.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])
{
    mxLogical *vlhs;

    if( nrhs != 1 )
        mexErrMsgTxt("Need exactly one input argument\n");
    if( !mxIsLogical(prhs[0]) )
        mexErrMsgTxt("Input argument must be logical\n");
    if( mxGetNumberOfDimensions(prhs[0]) != 2 )
        mexErrMsgTxt("Input argument has too many dimensions\n");
    if( mxGetNumberOfElements(prhs[0]) != 5 )
        mexErrMsgTxt("Input argument must have five elements\n");
    
    plhs[0] = mxDuplicateArray(prhs[0]);
    vlhs = mxGetLogicals(plhs[0]);
    
    *(vlhs+4) = *(vlhs+0) | *(vlhs+1) | *(vlhs+2) | *(vlhs+3);
}

Subject: Boolean variables in a MEX file

From: evansstev@yahoo.com

Date: 19 Nov, 2007 21:32:44

Message: 4 of 4

On Nov 10, 5:03 am, James Tursa <aclassyguywithakno...@hotmail.com>
wrote:
> As Chris already said, it is not clear that you actually want a mex
> file that handles mxLogical data as input. Maybe your data is 0's and
> 1's but it is always double class. But taking you at your word, here
> are some comments about your code:
>
> (Chris has already noted the first two. I simply repeat them here)
>
> 1) You have made no checks for proper input type, size, etc. This can
> cause nasty problems with memory if you don't pass the function
> exactly what the code expects. Always check the input. For example, if
> you pass in a double class variable, then you have passed in 8*5 = 40
> bytes of data (plus the overhead stuff), but this line
>
> > memcpy(mxGetLogicals(plhs[0]),V,5*mxGetElementSize(plhs[0]));
>
> only copies 5*1 = 5 bytes of data. In fact, if the first element of
> the double vector you passed in is 0 (such as your example), then the
> data area of prhs[0] will start with eight bytes of exactly 0, the
> first four of which you used for your logical calculations. You will
> always get five zeros for your result in this case. Things would have
> gotten really nasty here had you used prhs[0] for any memory copying
> in a statement like this. For example, consider a similar statement:
>
> memcpy(mxGetLogicals(plhs[0]),V,5*mxGetElementSize(prhs[0]));
>
> I only changed the argument of mxGetElementSize to use prhs[0] instead
> of plhs[0]. This would cause 40 bytes to be written to a data area
> only capable of holding 5 bytes, probably resulting in a MATLAB crash.
>
> 2) You change the actual memory of the input variable. This should
> *never* be done. You have actually changed the value of the input
> variable (bad enough), but may *also* have inadvertantly changed the
> value of a completely different variable in the MATLAB workspace (one
> that isn't even involved in the argument list) because it may have
> shared memory with the input variable you are using. This is very bad,
> so never do this.
>
> 3) You are assuming that an mxLogical is the same thing as a bool in
> c. This is not a safe thing to do in general. mxLogical may be a bool
> on some systems, but it may be something else (e.g., unsigned char) on
> other systems. Since MATLAB uses 1 byte for a logical element in the
> MATLAB workspace, they will probably always define mxLogical to be
> something that is guaranteed to be 1 byte on the system it is
> installed. For c in general the only thing you can count on is that a
> char (or unsigned char) is 1 byte. You can't count on anything else.
> You can't be sure how many bytes a short is, an int is, a long is, etc
> etc. And you can't be sure how many bytes a bool is either. Unless you
> know a lot about the system you will be running on ahead of time, the
> only data length you can count on is char and unsigned char being 1
> byte. A lot of systems (most?) these days define a bool to be 1 byte,
> but strictly speaking this is processor dependent. So ... I advise
> against using bool in your code. Use mxLogical, since MATLAB has
> supplied that data type for you to use.
>
> 4) When using mxLogicals there is the problem that you don't know
> exactly what it is (or will be if your code gets used on another
> system). Will the underlying type be a bool? An unsigned char? So this
> will have to be kept in mind when working with them in your code and
> dereferencing them. I chose to use the bitwise operator | instead of
> the logical operator || so that there wouldn't be any inadvertant type
> conversions going on with this section of code:
>
> > *(V+4) = *(V+0)||*(V+1)||*(V+2)||*(V+3);
>
> The way you have it written, if the underlying type is unsigned char,
> then the result of the logical operations will be a bool, and then the
> final bool result will be cast back into an unsigned char. It would
> not be obvious to a casual reader that there was type conversions
> going on behind the scenes here. By rewriting it like this:
>
> *(V+4) = *(V+0) | *(V+1) | *(V+2) | *(V+3);
>
> the bitwise operator keeps all of the intermediate and final result
> types the same throughout the operations, regardless of what mxLogical
> may really be. There are no hidden type conversions going on behind
> the scenes.
>
> The other advantage of using | is that the underlying bits of an
> mxLogical true value are kept intact, regardless of what they might
> be. As it happens, MATLAB uses the value 1 for logic true and so does
> c for a bool value true, so there would not have been a problem here
> using ||. But a similar construct like this in a Fortran mex file
> would be a problem since logical true values can be -1 in Fortran,(all
> bits set for a twos complement integer). (I mostly make this point for
> other readers who might be Fortran mex programmers.)
>
> 5) When you are returning an mxArray of exactly the same class & size
> etc. as an input mxArray, I find it convenient to use the
> mxDuplicateArray function rather than getting the sizes, creating the
> dims array, calling the mxCreate... etc function. Then I modify the
> data in the new duplicate mxArray. The resulting code is often
> simpler. mxDuplicateArray makes a deep copy, so you are assured that
> there will be no shared data with the original.
>
> Below I have included a version of your code that I have rewritten
> according to my comments.
>
> James Tursa
>
> #include "mex.h"
> #include "matrix.h"
>
> void mexFunction(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])
> {
> mxLogical *vlhs;
>
> if( nrhs != 1 )
> mexErrMsgTxt("Need exactly one input argument\n");
> if( !mxIsLogical(prhs[0]) )
> mexErrMsgTxt("Input argument must be logical\n");
> if( mxGetNumberOfDimensions(prhs[0]) != 2 )
> mexErrMsgTxt("Input argument has too many dimensions\n");
> if( mxGetNumberOfElements(prhs[0]) != 5 )
> mexErrMsgTxt("Input argument must have five elements\n");
>
> plhs[0] = mxDuplicateArray(prhs[0]);
> vlhs = mxGetLogicals(plhs[0]);
>
> *(vlhs+4) = *(vlhs+0) | *(vlhs+1) | *(vlhs+2) | *(vlhs+3);
>
>
>
> }- Hide quoted text -
>
> - Show quoted text -


     I have had a chance to implement the changes that you suggested,
and am happy to say that your solution works very well! I suspected
that if I could get this MEX function to work with boolean variables,
the function would be much faster. As of now, I have noticed that
functions based on your changes work approximately 3 times faster than
with type "double" variables.
     I want to thank all who responded to my post. All of your
suggestions have been very helpful. I don't work with MEX files very
often, and your inputs have saved me lots of time and discouragement.

 
Thanks again,

 
Steven Evans

Tags for this Thread

Add a New Tag:

Separated by commas
Ex.: root locus, bode

What are tags?

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.

rssFeed for this Thread

Contact us at files@mathworks.com