@@ -153,33 +153,57 @@ def _cmwc_random_sequence(num_elements, seed):
153153
154154 # Create constants needed for the algorithm. The constants and notation
155155 # follows from the above reference.
156- a = tf .tile (tf .constant ([3636507990 ], tf .int64 ), [parallelism ])
157- b = tf .tile (tf .constant ([2 ** 32 ], tf .int64 ), [parallelism ])
158- logb_scalar = tf .constant (32 , tf .int64 )
156+ a = tf .tile (tf .constant ([3636507990 ], tf .uint64 ), [parallelism ])
157+ b = tf .tile (tf .constant ([2 ** 32 ], tf .uint64 ), [parallelism ])
158+ logb_scalar = tf .constant (32 , tf .uint64 )
159159 logb = tf .tile ([logb_scalar ], [parallelism ])
160- f = tf .tile (tf .constant ([0 ], dtype = tf .int64 ), [parallelism ])
161- bits = tf .constant (0 , dtype = tf .int64 , name = 'bits' )
160+ f = tf .tile (tf .constant ([0 ], dtype = tf .uint64 ), [parallelism ])
161+ bits = tf .constant (0 , dtype = tf .uint64 , name = 'bits' )
162162
163163 # TensorArray used in tf.while_loop for efficiency.
164164 values = tf .TensorArray (
165165 dtype = tf .float64 , size = num_iters , element_shape = [parallelism ])
166166 # Iteration counter.
167167 num = tf .constant (0 , dtype = tf .int32 , name = 'num' )
168168 # TensorFlow constant to be used at multiple places.
169- val_53 = tf .constant (53 , tf .int64 , name = 'val_53' )
169+ val_53 = tf .constant (53 , tf .uint64 , name = 'val_53' )
170170
171171 # Construct initial sequence of seeds.
172172 # From a single input seed, we construct multiple starting seeds for the
173173 # sequences to be computed in parallel.
174174 def next_seed_fn (i , val , q ):
175- val = val ** 7 + val ** 6 + 1 # PRBS7.
175+ # Proper 7-bit LFSR (Fibonacci) for polynomial x^7 + x^6 + 1.
176+ # We take lower 7 bits of val as state.
177+ state = tf .bitwise .bitwise_and (val , tf .constant (0x7F , tf .uint64 ))
178+ # Avoid zero state which gets stuck in LFSR.
179+ state = tf .bitwise .bitwise_or (
180+ state ,
181+ tf .cast (tf .equal (state , tf .constant (0 , tf .uint64 )), tf .uint64 )
182+ )
183+ # Feedback bit = bit 7 (index 6) ^ bit 6 (index 5)
184+ feedback = tf .bitwise .bitwise_and (
185+ tf .bitwise .bitwise_xor (
186+ tf .bitwise .right_shift (state , tf .constant (6 , tf .uint64 )),
187+ tf .bitwise .right_shift (state , tf .constant (5 , tf .uint64 ))
188+ ),
189+ tf .constant (1 , tf .uint64 )
190+ )
191+ # Shift left and insert feedback
192+ val = tf .bitwise .bitwise_and (
193+ tf .bitwise .bitwise_or (
194+ tf .bitwise .left_shift (state , tf .constant (1 , tf .uint64 )),
195+ feedback
196+ ),
197+ tf .constant (0x7F , tf .uint64 )
198+ )
176199 q = q .write (i , val )
177200 return i + 1 , val , q
178201
179- q = tf .TensorArray (dtype = tf .int64 , size = parallelism , element_shape = ())
202+ q = tf .TensorArray (dtype = tf .uint64 , size = parallelism , element_shape = ())
203+ seed_u64 = tf .cast (seed , tf .uint64 )
180204 _ , _ , q = tf .while_loop (lambda i , _ , __ : i < parallelism ,
181205 next_seed_fn ,
182- [tf .constant (0 ), seed , q ])
206+ [tf .constant (0 ), seed_u64 , q ])
183207 c = q = q .stack ()
184208
185209 # The random sequence generation code.
@@ -193,9 +217,10 @@ def cmwc_step(f, bits, q, c, num, values):
193217 f .set_shape ((1 ,)) # Correct for failed shape inference.
194218 bits += logb_scalar
195219 def add_val (bits , f , values , num ):
220+ mask_53 = tf .constant (2 ** 53 - 1 , tf .uint64 )
196221 new_val = tf .cast (
197- tf .bitwise .bitwise_and (f , ( 2 ** val_53 - 1 ) ),
198- dtype = tf .float64 ) * (1 / 2 ** val_53 )
222+ tf .bitwise .bitwise_and (f , mask_53 ),
223+ dtype = tf .float64 ) * (1.0 / 2.0 ** 53 )
199224 values = values .write (num , new_val )
200225 f += tf .bitwise .right_shift (f , val_53 )
201226 bits -= val_53
0 commit comments