From: AlexHuber Huber on
Hello,
my question is: Find biggest index j such that z(j)<=C.

It is possible to do it like this:
max(find(z<=C))

But my vector z is quite huge (about 8*10^6 elements), and I feel there should be a more efficient way to solve this?
Has anybody an idea?

Thank you,
Alex
From: Bruno Luong on
"AlexHuber Huber" <mischamail(a)web.de> wrote in message <hnnfk6$gjq$1(a)fred.mathworks.com>...
> Hello,
> my question is: Find biggest index j such that z(j)<=C.
>
> It is possible to do it like this:
> max(find(z<=C))

find(z<=C,1,'last')

It returns empty if no such element is found.

Bruno
From: AlexHuber Huber on
"Bruno Luong" <b.luong(a)fogale.findmycountry> wrote in message <hnnger$sp0$1(a)fred.mathworks.com>...
> "AlexHuber Huber" <mischamail(a)web.de> wrote in message <hnnfk6$gjq$1(a)fred.mathworks.com>...
> > Hello,
> > my question is: Find biggest index j such that z(j)<=C.
> >
> > It is possible to do it like this:
> > max(find(z<=C))
>
> find(z<=C,1,'last')
>
> It returns empty if no such element is found.
>
> Bruno

Thank you! that's nice!
From: Jan Simon on
Dear Alex!

> > > max(find(z<=C))
> >
> > find(z<=C,1,'last')
> > Bruno

An equivalent MEX can be much faster, because it can stop the comparison z<=C after the first match is found and no temporary memory is needed for the logical array:

-------- File: maxFind_le.c
#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *P, C;
mwSize n;

// Insert the usual checks
// if (nrhs != 2) ... if(!mxIsDouble(prhs[0]) || !mxIsNumeric(prhs[1])) ...
// if (nlhs > 1) ...

n = mxGetNumberOfElements(prhs[0]);
P = mxGetPr(prhs[0]);
C = mxGetScalar(prhs[1]);

while (--n >= 0) {
if (P[n] <= C) {
plhs[0] = mxCreateDoubleScalar((double) (n + 1));
return;
}
}

plhs[0] = mxCreateDoubleMatrix(0, 0, mxREAL);
return;
}
-------- END: File

I tested this with x = 1:1e6 (Matlab 2009a, 1.5GHz Pentium M, WinXP, 100 repetitions):
1. If no match is found, e.g. C = -1:
MAX(FIND): 1.26 sec
FIND('last'): 1.23 sec.
MEX: 0.77 sec
2. If all elements are matching, e.g. C = 1e7:
MAX(FIND): 6.07 sec
FIND('last'): 1.08 sec
MEX: 0.0025 sec !!!
3. Medium element matchs, C = 1e6 / 2:
MAX(FIND): 3.35 sec
FIND('last'): 1.14 sec
MEX: 0.38 sec

If this comparison is a bottleneck in your program, I'd suggest to mex it!

Good luck, Jan
From: AlexHuber Huber on
"Jan Simon" <matlab.THIS_YEAR(a)nMINUSsimon.de> wrote in message <hpkueg$428$1(a)fred.mathworks.com>...
> Dear Alex!
>
> > > > max(find(z<=C))
> > >
> > > find(z<=C,1,'last')
> > > Bruno
>
> An equivalent MEX can be much faster, because it can stop the comparison z<=C after the first match is found and no temporary memory is needed for the logical array:
>
> -------- File: maxFind_le.c
> #include "mex.h"
>
> void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
> {
> double *P, C;
> mwSize n;
>
> // Insert the usual checks
> // if (nrhs != 2) ... if(!mxIsDouble(prhs[0]) || !mxIsNumeric(prhs[1])) ...
> // if (nlhs > 1) ...
>
> n = mxGetNumberOfElements(prhs[0]);
> P = mxGetPr(prhs[0]);
> C = mxGetScalar(prhs[1]);
>
> while (--n >= 0) {
> if (P[n] <= C) {
> plhs[0] = mxCreateDoubleScalar((double) (n + 1));
> return;
> }
> }
>
> plhs[0] = mxCreateDoubleMatrix(0, 0, mxREAL);
> return;
> }
> -------- END: File
>
> I tested this with x = 1:1e6 (Matlab 2009a, 1.5GHz Pentium M, WinXP, 100 repetitions):
> 1. If no match is found, e.g. C = -1:
> MAX(FIND): 1.26 sec
> FIND('last'): 1.23 sec.
> MEX: 0.77 sec
> 2. If all elements are matching, e.g. C = 1e7:
> MAX(FIND): 6.07 sec
> FIND('last'): 1.08 sec
> MEX: 0.0025 sec !!!
> 3. Medium element matchs, C = 1e6 / 2:
> MAX(FIND): 3.35 sec
> FIND('last'): 1.14 sec
> MEX: 0.38 sec
>
> If this comparison is a bottleneck in your program, I'd suggest to mex it!
>
> Good luck, Jan

Thanks so much for your efforts! Actually I've never worked with mex and my last C programming experience is also quite long ago, but maybe I really should learn about these things in future, since this really sounds interesting to me! Thanks.