/* ************************************************************ MODULE sdmaux*.c -- Several low-level subroutines for the mex-files in the Self-Dual-Minimization package. % This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko % Copyright (C) 2005 McMaster University, Hamilton, CANADA (since 1.1) % % Copyright (C) 2001 Jos F. Sturm (up to 1.05R5) % Dept. Econometrics & O.R., Tilburg University, the Netherlands. % Supported by the Netherlands Organization for Scientific Research (NWO). % % Affiliation SeDuMi 1.03 and 1.04Beta (2000): % Dept. Quantitative Economics, Maastricht University, the Netherlands. % % Affiliations up to SeDuMi 1.02 (AUG1998): % CRL, McMaster University, Canada. % Supported by the Netherlands Organization for Scientific Research (NWO). % % This program is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2 of the License, or % (at your option) any later version. % % This program is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with this program; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA % 02110-1301, USA ************************************************************ */ #include /* memcpy etc */ #include /* floor and log */ #include "blksdp.h" /* ************************************************************ COMPARISON/ SEARCHING ************************************************************ */ /* ------------------------------------------------------------ For ascending sort (e.g. 0,1,2,.. or a,b,c,..) : compare yields < 0 iff a < b, 0 iff a==b, > 0 iff a > b. ------------------------------------------------------------ */ /* Integer compare: (for ibsearch) */ char icmp(const mwIndex *a, const mwIndex *b) { return( (*a > *b) - (*a < *b) ); } /* Integer compare (with integer key): (for kiqsort) */ char kicmp(const keyint *a, const keyint *b) { return( (a->i > b->i) - (a->i < b->i) ); } /* Float compare (with integer key), for DESCENDING sort (e.g. 10,9,8,..).*/ char kdcmpdec(const keydouble *a, const keydouble *b) { return( (a->r < b->r) - (a->r > b->r) ); } /* ************************************************************ PROCEDURE intbsearch - search through (in strictly ascending order) sorted integer array. DIFFERENT FROM ansi BSEARCH, since it returns always the offset k=*pi, such that x(0:k-1) < key <= x(k:n-1). Thus, x(k) CAN be larger than key (viz. if key not in array). if x(0:n-1) < key then k=n. INPUT x - length n integer array key - integer to search for n - length of x UPDATED pi - On input, 0<= *pi; we'll search only in x[*pi,n-1]. On output, x(0:*pi-1) < key, x(*pi:n) >= key. NB1: *piIN <= *piOUT <= n, so possibly *piOUT=n. NB2: if *piIN==n then *piOUT=n. RETURNS 1 if found, 0 otherwise. If found, then x[*pi]=key, otherwise x[*pi] > key. ************************************************************ */ bool intbsearch(mwIndex *pi, const mwIndex *x, const mwIndex n, const mwIndex key) { mwIndex i,j,r; i = *pi; mxAssert(i >= 0,""); if(i < n){ if(x[i] < key){ r = n; /* ------------------------------------------------------------ During the loop, x[i] < key and r key < x[r], i.e. key has to be strictly within (i,r). Therefore, we also take j strictly in (i,r). ------------------------------------------------------------ */ for(j = (i+n) / 2; j > i; j = (i+r) / 2){ if(x[j] > key) r = j; /* new right limit */ else if(x[j] < key) i = j; /* new left limit */ else{ *pi = j; /* Found : x[j] == key */ return 1; } } *pi = r; /* x[r] > key */ return 0; /* not found: i==j==(r-1), x[r-1] < key < x[r] */ } /* ------------------------------------------------------------ If, for the initial i, x[i] >= key, then keep this i, and return found = (x[i] == key). ------------------------------------------------------------ */ else /* x[(i = *pi)] >= key */ return (x[i] == key); } return 0; /* if i>=n, i.e. the list is empty */ } /* ************************************************************ PROCEDURE intmbsearch - multi-bsearch: locate positions of ascending array y in the ascending array x. If y is a singleton, then this corresponds to regular bsearch. INPUT x, y - integer arrays of length xnnz and ynnz, resp. xnnz, ynnz - lengths of x and y, resp. bsize - size of mwIndex working array b; bsize = floor(log(ynnz+1)/log(2)). OUTPUT z - length ynnz+2 array. Sets z[0]=0, z[ynnz+1]=xnnz, and x[z[k+1]-1] < y[k] <= x[z[k+1]] for all k=0:ynnz-1. found - length ynnz array. found[k] = (x[z[k+1]] == y[k]). WORKING ARRAY b - length bsize iwork array; bsize = floor(log(ynnz+1)/log(2)). RETURNS 0 SUCCESS, -1 bsize too small. ************************************************************ */ char intmbsearch(mwIndex *z, bool *found, const mwIndex *x, const mwIndex xnnz, const mwIndex *y, const mwIndex ynnz, mwIndex *b, const mwIndex bsize) { mwIndex a,bk,k,m; mwIndex *zp1; bool isknegative; /* ------------------------------------------------------------ Init: ------------------------------------------------------------ */ mxAssert(xnnz >= 0 && ynnz >= 0,""); if(bsize < (mwIndex) floor(log(ynnz+1.0) / log(2.0))) return -1; /* ERROR: insufficient work space */ z[0] = 0; zp1 = z + 1; zp1[ynnz] = xnnz; if(ynnz == 0) return 0; /* ------------------------------------------------------------ Divide and Conquer: Divide y in binary way; k is current depth in tree; Still need to locate [y[a], y[bk]); the uncertainty interval in x is [z[a], zp1[bk]). Note that we located x[zp1[bk]-1] < y[bk] <= x[zp1[bk]]. All y[0:a-1] have already been located: x[z[a]-1] < y[a-1]. ------------------------------------------------------------ */ k = 0; a = 0; b[0] = ynnz; isknegative=0; while(!isknegative){ bk = b[k]; mxAssert(a < bk,""); /* ------------------------------------------------------------ y[a:bk-1] have not yet been located. Locate y[m] with a <= m < bk ------------------------------------------------------------ */ m = (mwIndex) floor((double) (a+bk-1)/2); zp1[m] = z[a]; /* must be in [z[a],zp1[bk]) */ found[m] = intbsearch(zp1+m, x, zp1[bk], y[m]); /* ------------------------------------------------------------ If a < m then m < bk-1 and we DESCEND in the tree to locate y[a,m-1]. ------------------------------------------------------------ */ if(m > a){ b[++k] = m; /* Locate y[a:m-1] */ mxAssert(k < bsize,""); /* Also b[k] < bk - 1 */ } /* ------------------------------------------------------------ If a = m = bk-2, then STAY on this level with a = m+1, i.e. ++a. We've located y[0:m]. ------------------------------------------------------------ */ else if(++a >= bk){ /* ------------------------------------------------------------ If a:bk-1 = {a}, i.e. m=a, then we finished this branch of the tree. We've located y[0:bk]. ASCEND in tree with a = bk+1. ------------------------------------------------------------ */ if(k>0) --k; else isknegative=1; mxAssert(k>=0,""); ++a; /* Note that a = bk+1 < b[k], see DESCEND */ mxAssert(a == bk+1,""); } } /* if k >=0 then proceed location on y[a,b[k]-1]. */ /* ------------------------------------------------------------ SUCCESS: return 0. ------------------------------------------------------------ */ return 0; }