ddlog.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include <stdint.h>
  2. #include <limits.h>
  3. #include <strings.h>
  4. #include <gmp.h>
  5. #include "ddlog.h"
  6. #include "group.h"
  7. #include "hss.h"
  8. uint32_t lookup[256];
  9. uint32_t offset[256];
  10. static const uint64_t topmask = ~(ULLONG_MAX >> halfstrip_size);
  11. static const uint64_t topbigmask = ~(ULLONG_MAX >> strip_size);
  12. static const uint64_t bottommask = (0x01 << halfstrip_size) -1;
  13. static inline
  14. void add_1(uint64_t *b, const size_t start, const size_t len, uint64_t a)
  15. {
  16. for (size_t i = start; a != 0; i = (i+1)%len) {
  17. const uint64_t r = b[i] + a;
  18. a = (r < a);
  19. b[i] = r;
  20. }
  21. /*
  22. we don't check for overflows in "i".
  23. If it happens, buy a lottery ticket and retry.
  24. */
  25. }
  26. uint32_t __attribute__((optimize("unroll-loops"))) convert(uint64_t * nn)
  27. {
  28. uint32_t steps;
  29. size_t head = 23;
  30. #define next_head ((head + 23) % 24)
  31. #define tail ((head + 1) % 24)
  32. #define next_tail ((head + 2) % 24)
  33. #define distinguished(x) (((x)[head] & topbigmask)) == 0
  34. /** Check the most significant block */
  35. const uint64_t x = nn[head];
  36. for (uint32_t w2 = halfstrip_size; w2 < 64-halfstrip_size; w2 += halfstrip_size) {
  37. if (!(x & (topmask >> w2))) {
  38. const size_t previous = (x >> (64 - halfstrip_size - w2 + halfstrip_size)) & bottommask;
  39. const uint32_t next = (x >> (64 - halfstrip_size - w2 - halfstrip_size)) & bottommask;
  40. if (next <= lookup[previous]) return w2 - offset[previous];
  41. }
  42. }
  43. for (steps = 64; !distinguished(nn); steps += 64) {
  44. const uint64_t x = nn[head];
  45. const uint64_t y = nn[next_head];
  46. if (!(x & bottommask)) {
  47. const size_t previous = (x >> halfstrip_size) & bottommask;
  48. const uint32_t next = y >> (64 - halfstrip_size);
  49. if (next <= lookup[previous]) return steps - halfstrip_size - offset[previous];
  50. }
  51. if (!(y & topmask)) {
  52. const size_t previous = x & bottommask;
  53. const uint32_t next = (y >> (64 - 2*halfstrip_size)) & bottommask;
  54. if (next <= lookup[previous]) return steps - offset[previous];
  55. }
  56. for (uint32_t w2 = halfstrip_size; w2 < 64-halfstrip_size; w2 += halfstrip_size) {
  57. if (!(y & (topmask >> w2))) {
  58. const size_t previous = (y >> (64 - halfstrip_size - w2 + halfstrip_size)) & bottommask;
  59. const uint32_t next = (y >> (64 - halfstrip_size - w2 - halfstrip_size)) & bottommask;
  60. if (next <= lookup[previous]) return steps + w2 - offset[previous];
  61. }
  62. }
  63. /**
  64. * We found no distinguished point.
  65. */
  66. const uint128_t a = (uint128_t) x * gg;
  67. const uint64_t al = (uint64_t) a;
  68. const uint64_t ah = (a >> 64);
  69. head = next_head;
  70. nn[tail] = al;
  71. add_1(nn, next_tail, 24, ah);
  72. }
  73. return steps;
  74. }
  75. uint32_t naif_convert(mpz_t n)
  76. {
  77. uint32_t i;
  78. mpz_t t;
  79. mpz_init_set_ui(t, 1);
  80. mpz_mul_2exp(t, t, 1536-strip_size);
  81. for (i = 0; mpz_cmp(n, t) > -1; i++) {
  82. mpz_mul_ui(n, n, 2);
  83. mpz_mod(n, n, p);
  84. }
  85. mpz_clear(t);
  86. return i;
  87. }
  88. void dlog_precompute()
  89. {
  90. for (size_t i = 0; i <= bottommask; i++) {
  91. uint32_t j = ffs(i) ? ffs(i) - 1 : halfstrip_size;
  92. lookup[i] = bottommask >> (halfstrip_size-j);
  93. offset[i] = j;
  94. }
  95. }