ddlog.c 2.9 KB

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