Home

[This page is auto-generated; please prefer to read the article’s PDF Form.]



[Prev]   [Up]   [Next]   

The Algorithm

First we observe that, there must exist integer r such that er belongs to the cycle and er equals at least one element among its next r elements (er+1,er+2,,er+r). Specifically, any integer r satisfies this condition if and only if:

(a) r l (er belongs to the cycle) and,

(b) r n (er equals any of its next r elements).

Note that, (r l and r n) can also be written as r max(l,n).

So, for any given l and n, all integers max(l,n) onwards satisfy the criteria for r. The Brent’s algorithm attempts to find r which is the minimum power of 2, 2p (p is a non-negative integer), such that 2p max(l,n). Now onwards, we will use r to denote this specific integer 2p.

By finding r and locating er, the algorithm will have located some element in the cycle (since er belongs to the cycle), and will then proceed to find l and n.

The algorithm works as follows. It sequentially checks if the candidates r= 20,21,22,, satisfy the criteria for the desired r. That is, whether er equals any of its next relements or not. To do that, it maintains two references M (mark) and R. For each r, M is kept at er while R steps through the next r elements comparing them with M (er). Note that this stepping of R will finally bring it at er+r = e2r. So, for checking the next candidate r, which is 2r, this reference R at e2r can be used to set the mark M for that next candidate.

Note that a candidate rdoes not satisfy the criteria if, either (a) er is outside the cycle (r< l), or (b) er is inside the cycle but is distinct from its next relements (r< n).

Following is an implementation of this algorithm in C. The above described part of this method will be referred as “Cycle-Searching” (the other part “Find l” will be discussed below). Whenever a reference, say R, is updated to f(R), we will call it one “step” taken by R.

Note that when the desired r is reached, the value of n can be found by counting the steps R has taken after er to reach the nearest element equaling er.

/* Parameter f is a function pointer.  
   Output values of n and l are returned via pointers pn and pl.  
 
   The elements e{i} are referred using type "void *". So,  
   function f has input and output type as "void *". */  
 
void brent(void *e0, void* f(void*), int *pn, int *pl)  
{  
  void *R, *M, *R0;  
  int i, r, cycle_found, count, j, n, l;  
 
  /***** Cycle-Searching *****/  
 
  /* initializations for the loop below */  
  M = f(e0);  
  r = 1;  
  R = f(M);  
  i = 2;  
  cycle_found = (R == M);  
 
  /* outer-loop invariants:  
 
       1. M = e{r}  
 
       2. R = e{i}  
 
       3. (cycle_found AND (i = r + n) AND (R = M)) OR  
          (!cycle_found AND (i = 2r)) */  
 
  while(!cycle_found)  
  {  
    r = 2*r;  
 
    M = R;  
 
    /* Now, M = R = e{r}. R will take (upto) r steps till e{2r} */  
 
    /* inner-loop invariant: R = e{i} */  
 
    while(i < 2*r && !cycle_found)  
    {  
      R = f(R);  
      i = i + 1;  
      cycle_found = (R == M);  
    }  
  }  
 
  n = i - r;  
 
  /***** Find l *****/  
 
  /* (M = e{r}) holds */  
 
  if(r%n != 0)  
  {  
    j = r + n - r%n;  
    i = r;  
 
    while(i < j)  
    {  
      M = f(M);  
      i = i + 1;  
    }  
 
    /* (M = e{j}) holds */  
  }  
 
  /* (M = e{multiple-of-n}) holds */  
  R0 = e0;  
  count = 0;  
 
  while(R0 != M)  
  {  
    R0 = f(R0);  
    M = f(M);  
    count++;  
  }  
 
  /* (R0 = M = e{l}) holds */  
 
  l = count;  
 
  *pn = n;  
  *pl = l;  
}

This algorithm finds minimum power of 2, r = 2p, such that 2p max(l,n). Since 2p is the minimum possible, we must have 2p1 < max(l,n), which can also be written as 2p < 2 max(l,n). So,

r < 2⋅max (l,n)

Also, this algorithm (the cycle-searching part) steps R total r + n times. So, the number of calls to f performed by it is upper-bounded by:

2 ⋅max(l,n)+ n

[Prev]   [Up]   [Next]