1 function [isMemberVec,indMemberVec]=
ismemberrows(inpLeftMat,inpRightMat,isInteger,forceMode)
3 persistent maxVal sqMaxVal logMaxVal;
8 [nLeftRows,nCols]=size(inpLeftMat);
9 if size(inpRightMat,2)~=nCols
11 'Number of columns in inpLeftMat and inpRightMat must be the same');
13 nRightRows=size(inpRightMat,1);
15 if nLeftRows==0||nRightRows==0||nCols==0
17 isMemberVec=
true(nLeftRows,1);
18 indMemberVec=
repmat(nRightRows,nLeftRows,1);
20 isMemberVec=
false(nLeftRows,1);
21 indMemberVec=zeros(nLeftRows,1);
26 isNum=isnumeric(inpLeftMat)&&isnumeric(inpRightMat);
28 if ~(isreal(inpLeftMat)&&isreal(inpRightMat))
29 % transform complex numbers to real ones separating them on real
32 inpLeftMat=[real(inpLeftMat) imag(inpLeftMat)];
33 inpRightMat=[real(inpRightMat) imag(inpRightMat)];
41 isLeftMat=isnan(inpLeftMat);
42 isRightMat=isnan(inpRightMat);
43 isLeftNan=any(isLeftMat);
44 isRightNan=any(isRightMat);
45 isInteger=~(isLeftNan||isRightNan);
50 [isMemberVec,indMemberVec]=
ismember(inpLeftMat,inpRightMat,
'legacy');
52 isMemberVec=
ismember(inpLeftMat,inpRightMat,
'legacy');
55 isMemberVec=
false(nLeftRows,1);
56 indMemberVec=zeros(nLeftRows,1);
60 isMemberVec(isLeftMat)=
true;
61 indMemberVec(isLeftMat)=find(isRightMat,1,
'last');
64 if isLeftNan||isRightNan
66 isRightMat=~isRightMat;
70 [isCurMemberVec,indCurMemberVec]=
ismember(inpLeftMat(isLeftMat),inpRightMat(isRightMat),
'legacy');
71 if isRightNan&&any(isCurMemberVec)
72 inpRightMat=find(isRightMat);
73 indCurMemberVec(isCurMemberVec)=inpRightMat(indCurMemberVec(isCurMemberVec));
75 isMemberVec(isLeftMat)=isCurMemberVec;
76 indMemberVec(isLeftMat)=indCurMemberVec;
78 isMemberVec(isLeftMat)=
ismember(inpLeftMat(isLeftMat),inpRightMat(isRightMat),
'legacy');
83 isForceMode=nargin>=4;
84 if ~strcmp(
class(inpLeftMat),
class(inpRightMat))
86 'Classes of inpLeftMat and inpRightMat differ');
88 if isempty(maxVal)||isempty(sqMaxVal)||isempty(logMaxVal)
89 maxVal=1/eps(
'double');
90 sqMaxVal=sqrt(maxVal);
91 logMaxVal=log2(maxVal);
94 isIntType=isinteger(inpLeftMat);
95 isLogicalType=islogical(inpLeftMat);
96 isCharType=ischar(inpLeftMat);
97 isInteger=isInteger||isIntType||isLogicalType||isCharType;
102 'Type of inpLeftMat and inpRightMat is wrong');
104 % reshape matrices into column vectors
105 inpLeftMat=inpLeftMat(:);
106 inpRightMat=inpRightMat(:);
107 isLeftMat=isfinite(inpLeftMat);
108 isRightMat=isfinite(inpRightMat);
109 if (all(isLeftMat)&&all(isRightMat))
110 minInpVal=min(min(inpLeftMat),min(inpRightMat));
111 maxInpVal=max(max(inpLeftMat),max(inpRightMat));
113 % replace non-finite numbers by finite ones
114 inpMat=[inpLeftMat(isLeftMat);inpRightMat(isRightMat)];
115 % determine range of finite values
120 minInpVal=min(inpMat);
121 maxInpVal=max(inpMat);
123 isLeftMat=~isLeftMat;
124 isRightMat=~isRightMat;
125 inpMat=[inpLeftMat(isLeftMat);inpRightMat(isRightMat)];
135 inpMat(isMat)=nextVal;
146 inpMat(isMat)=nextVal;
154 [
'Range of values in inpLeftMat and inpRightMat is ',...
155 'too large to process it correctly']);
162 inpMat(isMat)=nextVal;
164 % update non-finite values
165 curVal=sum(isLeftMat);
166 inpLeftMat(isLeftMat)=inpMat(1:curVal);
167 inpRightMat(isRightMat)=inpMat(curVal+1:end);
169 rangeVal=maxInpVal-minInpVal+1;
170 if rangeVal<=sqMaxVal
171 isInteger=all(fix(inpLeftMat)==inpLeftMat)&&...
172 all(fix(inpRightMat)==inpRightMat);
173 isnOptimized=~isInteger;
176 if isInteger&&isnOptimized
177 % calculate range of values
183 maxInpVal=double(intmax(
'uint16'));
187 inpLeftMat=inpLeftMat(:);
188 inpRightMat=inpRightMat(:);
190 minInpVal=double(min(min(inpLeftMat),min(inpRightMat)));
191 maxInpVal=double(max(max(inpLeftMat),max(inpRightMat)));
193 % determine whether optimized version may be performed or not
194 rangeVal=maxInpVal-minInpVal+1;
195 isnOptimized=rangeVal>sqMaxVal;
197 % reshape inpLeftMat and inpRightMat from column vectors into matrices
if 200 inpLeftMat=reshape(inpLeftMat,nLeftRows,nCols);
201 inpRightMat=reshape(inpRightMat,nRightRows,nCols);
204 isnOptimized=isnOptimized||~strcmpi(forceMode,
'optimized');
206 % determine what version (standard or optimized) is to be used
207 nRows=nLeftRows+nRightRows;
208 if rangeVal<=pow2(logMaxVal/nCols)
209 isOptimized=nRows>=3;
210 elseif nCols>=250&&nRows>=100
211 isOptimized=rangeVal<=pow2(nRows^3.62,-24);
213 isOptimized=rangeVal<=pow2(nRows^3.62,-34);
215 isnOptimized=~isOptimized;
218 % perform built-in version of
ismember 220 [isMemberVec,indMemberVec]=
ismember(inpLeftMat,inpRightMat,...
223 isMemberVec=
ismember(inpLeftMat,inpRightMat,
'rows');
227 % unite all values in single matrix
228 inpLeftMat=[inpLeftMat;inpRightMat];
230 inpLeftMat=double(inpLeftMat)+(1-minInpVal);
231 % calculate codes
for rows
232 allSizeVec=max(inpLeftMat,[],1);
236 %
break all columns on segments
238 curInd=max(find(cumprod(allSizeVec(iCol+1:end))<=maxVal,1,...
243 lenVec=horzcat(lenVec,curInd); %#ok<AGROW>
247 auxCell=cell(1,nCols);
249 auxCell{iCol}=inpLeftMat(:,iCol);
254 %
get column vector with codes
255 inpLeftMat=sub2ind(allSizeVec,auxCell{:});
257 inpLeftMat=inpLeftMat(:,1:nCols);
258 sizeVec=nan(1,nCols);
260 lenVec(end)=lenVec(end)+nCurCols-sum(lenVec);
261 %
if necessary, process last segment with single column
263 inpLeftMat(:,nCols)=auxCell{nCurCols};
264 sizeVec(nCols)=allSizeVec(nCurCols);
269 %
get codes
for all segments
270 leftIndVec=[1 cumsum(lenVec(1:nCurCols-1))+1];
272 curInd=leftIndVec(iCol)+(0:lenVec(iCol)-1);
273 [uniqueLinInd,~,inpLeftMat(:,iCol)]=
unique(...
274 sub2ind(allSizeVec(curInd),auxCell{curInd}),
'legacy');
275 sizeVec(iCol)=length(uniqueLinInd);
280 % perform built-in
ismember for codes
282 isMemberVec=
true(nLeftRows,1);
283 indMemberVec=nRightRows*ones(nLeftRows,1);
286 [isMemberVec,indMemberVec]=
ismember(inpLeftMat(1:nLeftRows),...
287 inpLeftMat(nLeftRows+1:end),
'legacy');
289 isMemberVec=
ismember(inpLeftMat(1:nLeftRows),...
290 inpLeftMat(nLeftRows+1:end),
'legacy');
function num2cell(in inpArray, in varargin)
NUM2CELL is an extension of Matlab built-in function "num2cell" designed to work correctly with empty...
function throwerror(in msgTag, in varargin)
THROWERROR works similarly to built-in ERROR function in case when there is no output arguments but s...
function ismemberrows(in inpLeftMat, in inpRightMat, in isInteger, in forceMode)
ISMEMBERROWS finds indices of rows from the first matrix in the second matrix, i.e. it is the more efficient version of ISMEMBER(. . .,'rows')
function repmat(in inpArray, in varargin)
function unique(in inpVec)
UNIQUE for arrays of any type.
function ismember(in leftVec, in rightVec, in varargin)
ISMEMBER - ismember implementation for arrays of any type.