Index: doc/theses/thierry_delisle_PhD/code/relaxed_list.hpp
===================================================================
--- doc/theses/thierry_delisle_PhD/code/relaxed_list.hpp	(revision b232745aa346d2a551cb84ea589c6e3eb116ad6a)
+++ doc/theses/thierry_delisle_PhD/code/relaxed_list.hpp	(revision a82a8f48595cd3928f52f4805810325533dd05bd)
@@ -8,4 +8,6 @@
 #define SNZM 4
 #define BIAS 5
+#define BACK 6
+#define BACKBIAS 7
 
 #ifndef VARIANT
@@ -68,5 +70,7 @@
 			"RELAXED: SNZI + DISCOVERED MASK",
 			"RELAXED: SNZI + MASK",
-			"RELAXED: SNZI + LOCAL BIAS"
+			"RELAXED: SNZI + LOCAL BIAS",
+			"RELAXED: SNZI + REVERSE RNG",
+			"RELAXED: SNZI + LOCAL BIAS + REVERSE RNG"
 		};
 		return names[VARIANT];
@@ -76,5 +80,5 @@
 		: numLists(numThreads * numQueues)
 	  	, lists(new intrusive_queue_t<node_t>[numLists])
-		#if VARIANT == SNZI || VARIANT == BIAS
+		#if VARIANT == SNZI || VARIANT == BIAS || VARIANT == BACK || VARIANT == BACKBIAS
 			, snzi( std::log2( numLists / (2 * numQueues) ), 2 )
 		#elif VARIANT == SNZM || VARIANT == DISCOVER
@@ -96,17 +100,5 @@
 		while(true) {
 			// Pick a random list
-			#if VARIANT == BIAS
-			unsigned r = tls.rng.next();
-			unsigned i;
-			if(0 == (r & 0xF)) {
-				i = r >> 4;
-			} else {
-				i = tls.my_queue + ((r >> 4) % 4);
-				tls.pick.push.local++;
-			}
-			i %= numLists;
-			#else
-			unsigned i = tls.rng.next() % numLists;
-			#endif
+			unsigned i = idx_from_r(tls.rng1.next(), VARIANT == BIAS || VARIANT == BACKBIAS);
 
 			#ifndef NO_STATS
@@ -117,5 +109,5 @@
 			if( !lists[i].lock.try_lock() ) continue;
 
-			#if VARIANT != SNZM && VARIANT != SNZI && VARIANT != DISCOVER && VARIANT != BIAS
+			#if VARIANT == VANILLA || VARIANT == BITMASK
 				__attribute__((unused)) int num = numNonEmpty;
 			#endif
@@ -131,4 +123,7 @@
 				#elif VARIANT == SNZI || VARIANT == BIAS
 					snzi.arrive(i);
+				#elif VARIANT == BACK || VARIANT == BACKBIAS
+					snzi.arrive(i);
+					tls.rng2.set_raw_state( tls.rng1.get_raw_state());
 				#elif VARIANT == SNZM
 					snzm.arrive(i);
@@ -145,5 +140,5 @@
 				#endif
 			}
-			#if VARIANT != SNZM && VARIANT != SNZI && VARIANT != DISCOVER && VARIANT != BIAS
+			#if VARIANT == VANILLA || VARIANT == BITMASK
 				assert(numNonEmpty <= (int)numLists);
 			#endif
@@ -154,5 +149,5 @@
 			#ifndef NO_STATS
 				tls.pick.push.success++;
-				#if VARIANT != SNZM && VARIANT != SNZI && VARIANT != DISCOVER && VARIANT != BIAS
+				#if VARIANT == VANILLA || VARIANT == BITMASK
 					tls.empty.push.value += num;
 					tls.empty.push.count += 1;
@@ -171,8 +166,8 @@
 				{
 					// Pick first list totally randomly
-					i = tls.rng.next() % numLists;
+					i = tls.rng1.next() % numLists;
 
 					// Pick the other according to the bitmask
-					unsigned r = tls.rng.next();
+					unsigned r = tls.rng1.next();
 
 					size_t mask = tls.mask.load(std::memory_order_relaxed);
@@ -197,6 +192,24 @@
 			while(snzi.query()) {
 				// Pick two lists at random
-				int i = tls.rng.next() % numLists;
-				// int j = tls.rng.next() % numLists;
+				int i = tls.rng1.next() % numLists;
+				int j = tls.rng1.next() % numLists;
+
+				if(auto node = try_pop(i, j)) return node;
+			}
+
+		#elif VARIANT == BACK
+			while(snzi.query()) {
+				// Pick two lists at random
+				int i = tls.rng2.prev() % numLists;
+				int j = tls.rng2.prev() % numLists;
+
+				if(auto node = try_pop(i, j)) return node;
+			}
+
+		#elif VARIANT == BACKBIAS
+			while(snzi.query()) {
+				// Pick two lists at random
+				int i = idx_from_r(tls.rng2.prev(), true);
+				int j = idx_from_r(tls.rng2.prev(), true);
 
 				if(auto node = try_pop(i, j)) return node;
@@ -206,7 +219,7 @@
 			while(snzi.query()) {
 				// Pick two lists at random
-				unsigned ri = tls.rng.next();
+				unsigned ri = tls.rng1.next();
 				unsigned i;
-				unsigned j = tls.rng.next();
+				unsigned j = tls.rng1.next();
 				if(0 == (ri & 0xF)) {
 					i = (ri >> 4) % numLists;
@@ -228,6 +241,6 @@
 				{
 					// Pick two random number
-					unsigned ri = tls.rng.next();
-					unsigned rj = tls.rng.next();
+					unsigned ri = tls.rng1.next();
+					unsigned rj = tls.rng1.next();
 
 					// Pick two nodes from it
@@ -270,6 +283,6 @@
 			while(snzm.query()) {
 				// Pick two lists at random
-				int i = tls.rng.next() % numLists;
-				int j = tls.rng.next() % numLists;
+				int i = tls.rng1.next() % numLists;
+				int j = tls.rng1.next() % numLists;
 
 				if(auto node = try_pop(i, j)) return node;
@@ -285,6 +298,6 @@
 					unsigned num = ((numLists - 1) >> 6) + 1;
 
-					unsigned ri = tls.rng.next();
-					unsigned rj = tls.rng.next();
+					unsigned ri = tls.rng1.next();
+					unsigned rj = tls.rng1.next();
 
 					unsigned wdxi = (ri >> 6u) % num;
@@ -314,6 +327,6 @@
 			while(numNonEmpty != 0) {
 				// Pick two lists at random
-				int i = tls.rng.next() % numLists;
-				int j = tls.rng.next() % numLists;
+				int i = tls.rng1.next() % numLists;
+				int j = tls.rng1.next() % numLists;
 
 				if(auto node = try_pop(i, j)) return node;
@@ -348,5 +361,5 @@
 		if( !list.lock.try_lock() ) return nullptr;
 
-		#if VARIANT != SNZM && VARIANT != SNZI && VARIANT != DISCOVER  && VARIANT != BIAS
+		#if VARIANT == VANILLA || VARIANT == BITMASK
 			__attribute__((unused)) int num = numNonEmpty;
 		#endif
@@ -371,5 +384,5 @@
 				__attribute__((unused)) bool ret = btr(tls.mask, bit);
 				snzm.depart(w);
-			#elif VARIANT == SNZI || VARIANT == BIAS
+			#elif VARIANT == SNZI || VARIANT == BIAS || VARIANT == BACK || VARIANT == BACKBIAS
 				snzi.depart(w);
 			#elif VARIANT == SNZM
@@ -390,10 +403,10 @@
 		// Unlock and return
 		list.lock.unlock();
-		#if VARIANT != SNZM && VARIANT != SNZI && VARIANT != DISCOVER && VARIANT != BIAS
+		#if VARIANT == VANILLA || VARIANT == BITMASK
 			assert(numNonEmpty >= 0);
 		#endif
 		#ifndef NO_STATS
 			tls.pick.pop.success++;
-			#if VARIANT != SNZM && VARIANT != SNZI && VARIANT != DISCOVER && VARIANT != BIAS
+			#if VARIANT == VANILLA || VARIANT == BITMASK
 				tls.empty.pop.value += num;
 				tls.empty.pop.count += 1;
@@ -403,9 +416,24 @@
 	}
 
+	inline unsigned idx_from_r(unsigned r, bool bias) {
+		unsigned i;
+		if(bias) {
+			if(0 == (r & 0xF)) {
+				i = r >> 4;
+			} else {
+				i = tls.my_queue + ((r >> 4) % 4);
+				tls.pick.push.local++;
+			}
+		} else {
+			i = r;
+		}
+		return i % numLists;
+	}
 
 public:
 
 	static __attribute__((aligned(128))) thread_local struct TLS {
-		Random     rng = { int(rdtscl()) };
+		Random     rng1 = { int(rdtscl()) };
+		Random     rng2 = { int(rdtscl()) };
 		unsigned   my_queue = (ticket++) * 4;
 		pick_stat  pick;
@@ -418,5 +446,5 @@
     	__attribute__((aligned(64))) std::unique_ptr<intrusive_queue_t<node_t> []> lists;
 private:
-	#if VARIANT == SNZI || VARIANT == BIAS
+	#if VARIANT == SNZI || VARIANT == BIAS || VARIANT == BACK || VARIANT == BACKBIAS
 		snzi_t snzi;
 	#elif VARIANT == SNZM || VARIANT == DISCOVER
Index: doc/theses/thierry_delisle_PhD/code/utils.hpp
===================================================================
--- doc/theses/thierry_delisle_PhD/code/utils.hpp	(revision b232745aa346d2a551cb84ea589c6e3eb116ad6a)
+++ doc/theses/thierry_delisle_PhD/code/utils.hpp	(revision a82a8f48595cd3928f52f4805810325533dd05bd)
@@ -35,19 +35,69 @@
 };
 
+// class Random {
+// private:
+// 	unsigned int seed;
+// public:
+// 	Random(int seed) {
+// 		this->seed = seed;
+// 	}
+
+// 	/** returns pseudorandom x satisfying 0 <= x < n. **/
+// 	unsigned int next() {
+// 		seed ^= seed << 6;
+// 		seed ^= seed >> 21;
+// 		seed ^= seed << 7;
+// 		return seed;
+//     	}
+// };
+
+constexpr uint64_t extendedEuclidY(uint64_t a, uint64_t b);
+constexpr uint64_t extendedEuclidX(uint64_t a, uint64_t b){
+    return (b==0) ? 1 : extendedEuclidY(b, a - b * (a / b));
+}
+constexpr uint64_t extendedEuclidY(uint64_t a, uint64_t b){
+    return (b==0) ? 0 : extendedEuclidX(b, a - b * (a / b)) - (a / b) * extendedEuclidY(b, a - b * (a / b));
+}
+
 class Random {
 private:
-	unsigned int seed;
+	uint64_t x;
+
+	static constexpr const uint64_t M  = 1ul << 48ul;
+	static constexpr const uint64_t A  = 25214903917;
+	static constexpr const uint64_t C  = 11;
+	static constexpr const uint64_t D  = 16;
+
+public:
+	static constexpr const uint64_t m  = M;
+	static constexpr const uint64_t a  = A;
+	static constexpr const uint64_t c  = C;
+	static constexpr const uint64_t d  = D;
+	static constexpr const uint64_t ai = extendedEuclidX(A, M);
 public:
 	Random(int seed) {
-		this->seed = seed;
+		this->x = seed * a;
 	}
 
 	/** returns pseudorandom x satisfying 0 <= x < n. **/
 	unsigned int next() {
-		seed ^= seed << 6;
-		seed ^= seed >> 21;
-		seed ^= seed << 7;
-		return seed;
-    	}
+		//nextx = (a * x + c) % m;
+		x = (A * x + C) & (M - 1);
+		return x >> D;
+	}
+	unsigned int prev() {
+		//prevx = (ainverse * (x - c)) mod m
+		unsigned int r = x >> D;
+		x = ai * (x - C) & (M - 1);
+		return r;
+	}
+
+	void set_raw_state(uint64_t _x) {
+		this->x = _x;
+	}
+
+	uint64_t get_raw_state() {
+		return this->x;
+	}
 };
 
