| 
					
				 | 
			
			
				@@ -1,204 +0,0 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define _GNU_SOURCE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <assert.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <limits.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <stdbool.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <stdio.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <stdint.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <string.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <unistd.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <linux/random.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <sys/syscall.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <sys/time.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <gmp.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define INIT_TIMEIT() \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  struct timeval __start, __end;                \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  double __sdiff = 0, __udiff = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define START_TIMEIT()                          \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gettimeofday(&__start, NULL) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define END_TIMEIT()                                                    \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gettimeofday(&__end, NULL);                                           \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  __sdiff += (__end.tv_sec - __start.tv_sec);                           \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  __udiff += (__end.tv_usec - __start.tv_usec) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define GET_TIMEIT()                            \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  __sdiff + __udiff * 1e-6 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define TIMEIT_FORMAT "%lf" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-typedef __uint128_t uint128_t; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * p is our prime modulus, and is 2^n - g 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * where g is referred to as "gamma" (built-in function in C, so transliterated) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const static char* p_str = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  "505CAF"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const static char* g_str = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  "11510609"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-mpz_t p, g; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-uint32_t gg = 11510609; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static uint8_t lookup[256]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static uint8_t offset[256]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static inline ssize_t 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-getrandom(void *buffer, size_t length, unsigned int flags) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return syscall(SYS_getrandom, buffer, length, flags); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-INIT_TIMEIT(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define strip_size 16 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define halfstrip_size ((strip_size)/2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static inline 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void add_1(uint64_t *b, const size_t start, const size_t len, uint64_t a) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (size_t i = start; a != 0; i = (i+1)%len) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const uint64_t r = b[i] + a; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    a = (r < a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    b[i] = r; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     we don't check for overflows in "i". 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     If it happens, buy a lottery ticket and retry. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-uint32_t convert(uint64_t * nn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  static const uint64_t topmask = ~(ULLONG_MAX >> halfstrip_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  static const uint64_t topbigmask = ~(ULLONG_MAX >> strip_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  static const uint64_t bottommask = (0x01  << halfstrip_size) -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  uint32_t w; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  uint32_t steps; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  size_t head = 23; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define next_head  ((head + 23) % 24) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define tail       ((head + 1)  % 24) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define next_tail  ((head + 2)  % 24) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define distinguished(x) (((x)[head] & topbigmask)) == 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /** Check the most significant block */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const uint64_t x = nn[head]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (uint32_t w2 = halfstrip_size; w2 < 64-halfstrip_size; w2 += halfstrip_size) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!(x & (topmask >> w2))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      for (w = w2-1; !(x & (topmask >> w)); w--); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      ++w; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (!(x & (topbigmask >> w))) return w; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (steps = 64; !distinguished(nn); steps += 64) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const uint64_t x = nn[head]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const uint64_t y = nn[next_head]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!(x & bottommask)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      const size_t previous = (x >> halfstrip_size) & bottommask; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      const uint8_t next = y >> (64 - halfstrip_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (next <= lookup[previous]) return steps - halfstrip_size - offset[previous]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!(y & topmask)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      const size_t previous = x & bottommask; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      const uint8_t next = (y >> (64 - 2*halfstrip_size)) & bottommask; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (next <= lookup[previous]) return steps - offset[previous]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (uint32_t w2 = halfstrip_size; w2 < 64-halfstrip_size; w2 += halfstrip_size) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (!(y & (topmask >> w2))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (w = w2-1; !(y & (topmask >> w)); w--); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ++w; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (!(y & (topbigmask >> w)))  return steps + w; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * We found no distinguished point. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const uint128_t a = (uint128_t) x * gg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const uint64_t al = (uint64_t) a; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const uint64_t ah = (a >> 64); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    head = next_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    nn[tail] = al; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    add_1(nn, next_tail, 24, ah); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return steps; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-uint32_t naif_convert(mpz_t n) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  uint32_t i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  mpz_t t; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  mpz_init_set_ui(t, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  mpz_mul_2exp(t, t, 1536-strip_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (i = 0; mpz_cmp(n, t) > -1; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    mpz_mul_2exp(n, n, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    mpz_mod(n, n, p); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  mpz_clear(t); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-int main() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  mpz_init_set_str(p, p_str, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  mpz_init_set_str(g, g_str, 10); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gmp_randstate_t _rstate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  unsigned long int _rseed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gmp_randinit_default(_rstate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  getrandom(&_rseed, sizeof(unsigned long int), GRND_NONBLOCK); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gmp_randseed_ui(_rstate, _rseed); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (size_t i = 0; i <= 0xFF; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    uint32_t j = ffs(i) ? ffs(i) - 1 : 8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    lookup[i] = 0xFF >> (8-j); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    offset[i] = j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  uint32_t converted; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (int i=0; i < (int) 15258; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    mpz_t n, n0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    mpz_inits(n, n0, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    mpz_urandomm(n0, _rstate, p); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    mpz_set(n, n0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    START_TIMEIT(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    converted = convert(n->_mp_d); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    END_TIMEIT(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    mpz_set(n, n0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#ifndef NDEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    uint32_t expected = naif_convert(n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //printf("%d %d\n", converted, expected); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    assert(converted == expected); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    mpz_clears(n, n0, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  printf(TIMEIT_FORMAT "\n", GET_TIMEIT()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  mpz_clears(p, g, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 |