def xrandrange(start=None, stop=None):
    '''
Produces an iterator similiar to xrange with the interface of range. 
The iterator yields random numbers from 0 <= x < *start* if *stop* is not
specified, or *start* <= x < *stop* if it is. Here's an example of xrandrange::

   >>> list(xrandrange(10))
   [2, 1, 0, 7, 4, 3, 8, 5, 9, 6]
   >>> list(xrandrange(10, 20))
   [11, 10, 16, 13, 12, 17, 14, 18, 15, 19]

'''

    if start is None and stop is None:
        raise ValueError('no stop point specified')

    if not start is None and stop is None:
        stop = start
        start = 0

    if start is None:
        start = 0

    rand_range = stop - start
    
    if rand_range <= 0:
        raise ValueError('empty range given')

    # +/-1 compensates for the fact that 0 is not generated by the lfsr
    bitsize = int(math.floor(math.log(rand_range+1, 2)))+1
    seed = random.randrange(0, 2 ** bitsize - 1)
    lfsr_gen = lfsr(bitsize, seed)

    for value in lfsr_gen:
        if not value > rand_range:
            yield value - 1 + start

        if value == seed:
            break
Produces an iterator similiar to xrange with the interface of range. 
The iterator yields random numbers from 0 <= x < *start* if *stop* is not
specified, or *start* <= x < *stop* if it is. Here's an example of xrandrange::

   >>> list(xrandrange(10))
   [2, 1, 0, 7, 4, 3, 8, 5, 9, 6]
   >>> list(xrandrange(10, 20))
   [11, 10, 16, 13, 12, 17, 14, 18, 15, 19]