File: binsearch.R

package info (click to toggle)
gtools 3.4.1-1
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 384 kB
  • ctags: 5
  • sloc: asm: 127; ansic: 69; makefile: 1
file content (134 lines) | stat: -rw-r--r-- 3,387 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# $Id: binsearch.R 1295 2007-08-08 13:38:18Z warnes $

binsearch <- function(fun, range, ..., target=0,
                      lower=ceiling(min(range)),upper=floor(max(range)),
                      maxiter=100, showiter=FALSE)
    {

      # initialize
      lo <- lower
      hi <- upper
      counter <- 0
      val.lo <- fun(lo,...)
      val.hi <- fun(hi,...)

      # check whether function is increasing or decreasing, & set sign
      # appropriately.
      if( val.lo > val.hi )
        sign <- -1
      else
        sign <- 1

      # check if value is outside specified range
      if(target * sign < val.lo * sign)
          outside.range <- TRUE
      else if(target * sign >  val.hi * sign)
          outside.range <- TRUE
      else
        outside.range <- FALSE

      # iteratively move lo & high closer together until we run out of
      # iterations, or they are adjacent, or they are identical
      while(counter < maxiter && !outside.range )
        {

          counter <- counter+1

          if(hi-lo<=1 || lo<lower || hi>upper) break;

          center <- round((hi - lo)/2 + lo ,0  )
          val <- fun(center, ...)

          if(showiter)
            {
              cat("--------------\n")
              cat("Iteration #", counter, "\n")
              cat("lo=",lo,"\n")
              cat("hi=",hi,"\n")
              cat("center=",center,"\n")
              cat("fun(lo)=",val.lo,"\n")
              cat("fun(hi)=",val.hi,"\n")
              cat("fun(center)=",val,"\n")
            }


          if( val==target )
            {
              val.lo <- val.hi <- val
              lo <- hi <- center
              break;
            }
          else if( sign*val < sign*target )
            {
              lo <- center
              val.lo <- val
            }
          else #( val > target )
            {
              hi <- center
              val.hi <- val
            }

        if(showiter)
          {
            cat("new lo=",lo,"\n")
            cat("new hi=",hi,"\n")
            cat("--------------\n")
          }

        }

      # Create return value
      retval <- list()
      retval$call <- match.call()
      retval$numiter <- counter

      if( outside.range )
        {
          if(target * sign < val.lo * sign)
            {
              warning("Reached lower boundary")
              retval$flag="Lower Boundary"
              retval$where=lo
              retval$value=val.lo
            }
          else #(target * sign >  val.hi * sign)
          {
            warning("Reached upper boundary")
            retval$flag="Upper Boundary"
            retval$where=hi
            retval$value=val.hi
          }
        }
      else if( counter >= maxiter )
        {
          warning("Maximum number of iterations reached")
          retval$flag="Maximum number of iterations reached"
          retval$where=c(lo,hi)
          retval$value=c(val.lo,val.hi)
        }
      else if( val.lo==target )
        {
          retval$flag="Found"
          retval$where=lo
          retval$value=val.lo
        }
      else if( val.hi==target )
        {
          retval$flag="Found"
          retval$where=hi
          retval$value=val.hi
        }
      else
        {
          retval$flag="Between Elements"
          retval$where=c(lo, hi)
          retval$value=c(val.lo, val.hi)
        }

      return(retval)

    }