4 Adapted from http://javarng.googlecode.com/svn/trunk/com/modp/random/BlumBlumShub.java
6 Original license follows:-
8 Copyright 2005, Nick Galbreath -- nickg [at] modp [dot] com
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions are
15 Redistributions of source code must retain the above copyright
16 notice, this list of conditions and the following disclaimer.
18 Redistributions in binary form must reproduce the above copyright
19 notice, this list of conditions and the following disclaimer in the
20 documentation and/or other materials provided with the distribution.
22 Neither the name of the modp.com nor the names of its
23 contributors may be used to endorse or promote products derived from
24 this software without specific prior written permission.
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 This is the standard "new" BSD license:
39 http://www.opensource.org/licenses/bsd-license.php
46 from math import ceil as _ceil, log as _log
49 class BlumBlumShub(object):
51 def getPrime(self, bits):
53 Generate appropriate prime number for use in Blum-Blum-Shub.
55 This generates the appropriate primes (p = 3 mod 4) needed to compute the
56 "n-value" for Blum-Blum-Shub.
57 bits - Number of bits in prime
61 p = primes.bigppr(bits);
66 def generateN(self, bits):
68 This generates the "n value" for use in the Blum-Blum-Shub algorithm.
69 bits - The number of bits of security
72 p = self.getPrime(bits/2)
73 q = self.getPrime(bits/2)
75 # make sure p != q (almost always true, but just in case, check)
77 q = getPrime(self, bits/2);
79 # print "GenerateN - p = " + repr(p) + ", q = " + repr(q)
83 def __init__(self, bits):
85 Constructor, specifing bits for n.
88 self.n = self.generateN(bits)
89 # print "n set to " + repr(self.n)
90 length = self.bitLen(self.n)
91 seed = random.getrandbits(length)
96 Sets or resets the self.n value
100 def setSeed(self, seed):
102 Sets or resets the seed value and internal state.
105 self.state = seed % self.n
111 " Get the bit lengh of a positive number"
119 def next(self, numBits):
120 self.state = (self.state**2) % self.n
121 return float(self.state)/self.n
124 self.state = (self.state**2) % self.n
125 return float(self.state)/self.n
128 def sample(self, population, k):
129 """Chooses k unique random elements from a population sequence.
131 Returns a new list containing elements from the population while
132 leaving the original population unchanged. The resulting list is
133 in selection order so that all sub-slices will also be valid random
134 samples. This allows raffle winners (the sample) to be partitioned
135 into grand prize and second place winners (the subslices).
137 Members of the population need not be hashable or unique. If the
138 population contains repeats, then each occurrence is a possible
139 selection in the sample.
141 To choose a sample in a range of integers, use xrange as an argument.
142 This is especially fast and space efficient for sampling from a
143 large population: sample(xrange(10000000), 60)
146 # Sampling without replacement entails tracking either potential
147 # selections (the pool) in a list or previous selections in a set.
149 # When the number of selections is small compared to the
150 # population, then tracking selections is efficient, requiring
151 # only a small set and an occasional reselection. For
152 # a larger number of selections, the pool tracking method is
153 # preferred since the list takes less space than the
154 # set and it doesn't suffer from frequent reselections.
158 raise ValueError("sample larger than population")
162 setsize = 21 # size of a small set minus size of an empty list
164 setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets
165 if n <= setsize or hasattr(population, "keys"):
166 # An n-length list is smaller than a k-length set, or this is a
167 # mapping type so the other algorithm wouldn't work.
168 pool = list(population)
169 for i in xrange(k): # invariant: non-selected at [0,n-i)
170 j = _int(random() * (n-i))
172 pool[j] = pool[n-i-1] # move non-selected item into vacancy
176 selected_add = selected.add
178 j = _int(random() * n)
180 j = _int(random() * n)
182 result[i] = population[j]
183 except (TypeError, KeyError): # handle (at least) sets
184 if isinstance(population, list):
186 return self.sample(tuple(population), k)
192 bbs = BlumBlumShub(159);
193 bbs.setN(18532395500947174450709383384936679868383424444311405679463280782405796233163977*39688644836832882526173831577536117815818454437810437210221644553381995813014959)
194 bbs.setSeed(18532395500947174450709383384936679868383424444311)
196 #print "Generating 10 numbers"
197 for i in range (0,10):
200 print bbs.sample(xrange(100),55)
202 #print bbs.sample(range(10),5)
203 if __name__ == "__main__":