hash.c 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #ifndef __COSMOPOLITAN__
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #endif
  5. #define word unsigned long
  6. static word Null;
  7. static inline int IsTwoPow(word x) {
  8. return !(x & (x - 1));
  9. }
  10. static inline int Bsr(word x) {
  11. #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
  12. return __builtin_clzll(x) ^ 63;
  13. #else
  14. static const char kDebruijn[64] = {
  15. 0, 47, 1, 56, 48, 27, 2, 60, 57, 49, 41, 37, 28, 16, 3, 61,
  16. 54, 58, 35, 52, 50, 42, 21, 44, 38, 32, 29, 23, 17, 11, 4, 62,
  17. 46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43, 31, 22, 10, 45,
  18. 25, 39, 14, 33, 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63,
  19. };
  20. x |= x >> 1;
  21. x |= x >> 2;
  22. x |= x >> 4;
  23. x |= x >> 8;
  24. x |= x >> 16;
  25. x |= x >> 32;
  26. return kDebruijn[(x * 0x03f79d71b4cb0a89) >> 58];
  27. #endif
  28. }
  29. static word Hash(word h, word x, word a, word b, word c) {
  30. return (((h + x) * a + b) >> c) & (Null / 2 - 1);
  31. }
  32. static word Ok(word a, word b, word c) {
  33. return Hash(Hash(Hash(0, 'L', a, b, c), 'I', a, b, c), 'N', a, b, c) == 0 &&
  34. Hash(0, 'T', a, b, c) == 1 &&
  35. Hash(0, 'T', a, b, c) != Hash(0, 'U', a, b, c);
  36. }
  37. static int Usage(const char *prog) {
  38. fprintf(stderr, "Usage: %s NULL\n", prog);
  39. fprintf(stderr, "Finds magic numbers for SectorLISP Hash()\n");
  40. return 1;
  41. }
  42. int main(int argc, char *argv[]) {
  43. word a, b, c;
  44. if (argc > 1) {
  45. Null = strtoul(argv[1], 0, 0);
  46. if (Null < 64) {
  47. fprintf(stderr, "Error: Null is too small\n");
  48. return Usage(argv[0]);
  49. }
  50. if (!IsTwoPow(Null)) {
  51. fprintf(stderr, "Error: Null must be two power\n");
  52. return Usage(argv[0]);
  53. }
  54. } else {
  55. /* Null = 040000; */
  56. Null = 64;
  57. }
  58. for (;; Null <<= 1) {
  59. printf("\n");
  60. printf("#define Null %#lo\n", Null);
  61. fflush(stdout);
  62. for (a = 0; a < Null / 2; ++a) {
  63. for (c = 0; c <= Bsr(Null / 2) / 2; ++c) {
  64. /* for (b = 0; b < Null; ++b) { */
  65. /* solve 1 = ('T' * a + b) / 2^c for b */
  66. b = (((1<<c) - a * 'T') & (Null/2-1));
  67. if (Ok(a, b, c)) {
  68. if (c) {
  69. printf("return (((h + x) * %lu + %lu) >> %lu) & (Null/2-1);\n", a, b, c);
  70. } else {
  71. printf("return ((h + x) * %lu + %lu) & (Null/2-1);\n", a, b);
  72. }
  73. }
  74. }
  75. }
  76. }
  77. return 0;
  78. }