version 16.0 mata: real scalar _bcsf_bracketing(pointer (real scalar function) scalar yfun, real scalar y, real scalar yfarleft, real scalar yfarright, real scalar mbracket, real scalar scalefactor, real matrix bracketmat, real scalar leftindex, real scalar rightindex) { /* Bracketing a y-value for a bounded monotonic step function yfun(x), extending the bracket matrix if necessary. The returned result is a return code, equal to zero if the bracket matrix was updated without error. yfun() is a pointer to the function yfun(x) to be used in bracketing. y is the input y-value to be bracketed. yfarleft is the input left limiting value of yfun(x) as x thends to infinity. yfarright is the input right limiting value of yfun(x) as x tends to minus infinity. mbracket is the input maximum number of brackets in the bracket matrix. scalefactor is the factor to scale existing extreme x-brackets to produce candidates for additional extreme x-brackets. bracketmat is the bracket matrix to be searched (and updated if necessary), with the ordered x-brackets in column 1 and the corresponding y-brackets in column 2 and at least 2 rows, of which the first and the last should contain opposite-signed x-brackets in the first column. leftindex is the output left bracket index. rightindex is the output right bracket index. *! Author: Roger Newson. *! Date: 23 April 2006. */ real scalar farsign, newsign, xnew, ynew /* farsign stores the sign of the difference between a limiting y-value and an extreme y-bracket. newsign stores the sign of the difference between a new y-value and an extreme y-bracket. xnew stores a new x-value. ynew stores a new y-value. */ /* Conformability, missingness and consistency checks */ if(cols(bracketmat)!=2 | rows(bracketmat)<2 | rows(bracketmat)>mbracket){ return(1) } if(missing(bracketmat) | missing(y) | missing(yfarleft) | missing(yfarright) | missing(mbracket) | missing(scalefactor)){ return(2) } if(sign(bracketmat[1,1]) :* sign(bracketmat[rows(bracketmat),1]) != -1){ return(3) } if(scalefactor<=1){ return(4) } /* Left-extend bracket matrix if necessary */ xnew=bracketmat[1,1] ynew=bracketmat[1,2] farsign=sign(yfarleft-ynew) newsign=sign(y-ynew) if(missing(farsign) | missing(newsign)){ return(5) } while(farsign!=-newsign & farsign!=0){ if(rows(bracketmat)>=mbracket){ return(5) } xnew=scalefactor*xnew if(missing(xnew)){ return(5) } ynew=(*yfun)(xnew) if(missing(ynew)){ return(5) } farsign=sign(yfarleft-ynew) newsign=sign(y-ynew) if(missing(farsign) | missing(newsign)){ return(5) } bracketmat = (xnew,ynew) \ bracketmat } /* Right-extend bracket matrix if necessary */ xnew=bracketmat[rows(bracketmat),1] ynew=bracketmat[rows(bracketmat),2] farsign=sign(yfarright-ynew) newsign=sign(y-ynew) if(missing(farsign) | missing(newsign)){ return(6) } while(farsign!=-newsign & farsign!=0){ if(rows(bracketmat)>=mbracket){ return(6) } xnew=scalefactor*xnew if(missing(xnew)){ return(6) } ynew=(*yfun)(xnew) if(missing(ynew)){ return(6) } farsign=sign(yfarright-ynew) newsign=sign(y-ynew) if(missing(farsign) | missing(newsign)){ return(6) } bracketmat = bracketmat \ (xnew,ynew) } /* Locate left bracket index */ leftindex=rows(bracketmat) ynew=bracketmat[leftindex,2] farsign=sign(yfarleft-ynew) newsign=sign(y-ynew) if(missing(farsign) | missing(newsign)){ return(7) } while(farsign!=-newsign & farsign!=0){ leftindex-- if(leftindex<1){ return(7) } ynew=bracketmat[leftindex,2] farsign=sign(yfarleft-ynew) newsign=sign(y-ynew) if(missing(farsign) | missing(newsign)){ return(7) } } /* Locate right bracket index */ rightindex=1 ynew=bracketmat[rightindex,2] farsign=sign(yfarright-ynew) newsign=sign(y-ynew) if(missing(farsign) | missing(newsign)){ return(8) } while(farsign!=-newsign & farsign!=0){ rightindex++ if(rightindex>rows(bracketmat)){ return(8) } ynew=bracketmat[rightindex,2] farsign=sign(yfarright-ynew) newsign=sign(y-ynew) if(missing(farsign) | missing(newsign)){ return(8) } } return(0) } end