diff options
Diffstat (limited to 'src/utils.h')
| -rw-r--r-- | src/utils.h | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..0c0b4d1 --- /dev/null +++ b/src/utils.h | |||
| @@ -0,0 +1,125 @@ | |||
| 1 | _static int64_t factorial(int64_t); | ||
| 2 | _static bool isperm(uint8_t *, int64_t); | ||
| 3 | _static int64_t permtoindex(uint8_t *, int64_t); | ||
| 4 | _static void indextoperm(int64_t, int64_t, uint8_t *); | ||
| 5 | _static int permsign(uint8_t *, int64_t); | ||
| 6 | |||
| 7 | _static int64_t | ||
| 8 | factorial(int64_t n) | ||
| 9 | { | ||
| 10 | int64_t i, ret; | ||
| 11 | |||
| 12 | if (n > _max_factorial) { | ||
| 13 | LOG("Error: won't compute factorial for n=%" PRId64 " because" | ||
| 14 | " it is larger than %" PRId64 "\n", n, _max_factorial); | ||
| 15 | return -1; | ||
| 16 | } | ||
| 17 | |||
| 18 | if (n < 0) | ||
| 19 | return 0; | ||
| 20 | |||
| 21 | for (i = 1, ret = 1; i <= n; i++) | ||
| 22 | ret *= i; | ||
| 23 | |||
| 24 | return ret; | ||
| 25 | } | ||
| 26 | |||
| 27 | _static bool | ||
| 28 | isperm(uint8_t *a, int64_t n) | ||
| 29 | { | ||
| 30 | int64_t i; | ||
| 31 | bool aux[_max_factorial+1]; | ||
| 32 | |||
| 33 | if (n > _max_factorial) { | ||
| 34 | LOG("Error: won't compute 'isperm()' for n=%" PRId64 " because" | ||
| 35 | " it is larger than %" PRId64 "\n", n, _max_factorial); | ||
| 36 | return false; | ||
| 37 | } | ||
| 38 | |||
| 39 | memset(aux, false, n); | ||
| 40 | |||
| 41 | for (i = 0; i < n; i++) { | ||
| 42 | if (a[i] < 0 || a[i] >= n) | ||
| 43 | return false; | ||
| 44 | else | ||
| 45 | aux[a[i]] = true; | ||
| 46 | } | ||
| 47 | |||
| 48 | for (i = 0; i < n; i++) | ||
| 49 | if (!aux[i]) | ||
| 50 | return false; | ||
| 51 | |||
| 52 | return true; | ||
| 53 | } | ||
| 54 | |||
| 55 | _static int64_t | ||
| 56 | permtoindex(uint8_t *a, int64_t n) | ||
| 57 | { | ||
| 58 | int64_t i, j, c, ret; | ||
| 59 | |||
| 60 | if (n > _max_factorial) { | ||
| 61 | LOG("Error: won't compute 'permtoindex()' for n=%" PRId64 | ||
| 62 | " because it is larger than %" PRId64 "\n", | ||
| 63 | n, _max_factorial); | ||
| 64 | return -1; | ||
| 65 | } | ||
| 66 | |||
| 67 | if (!isperm(a, n)) | ||
| 68 | return -1; | ||
| 69 | |||
| 70 | for (i = 0, ret = 0; i < n; i++) { | ||
| 71 | for (j = i+1, c = 0; j < n; j++) | ||
| 72 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 73 | ret += factorial(n-i-1) * c; | ||
| 74 | } | ||
| 75 | |||
| 76 | return ret; | ||
| 77 | } | ||
| 78 | |||
| 79 | _static void | ||
| 80 | indextoperm(int64_t p, int64_t n, uint8_t *r) | ||
| 81 | { | ||
| 82 | int64_t i, j, c; | ||
| 83 | uint8_t a[_max_factorial+1]; | ||
| 84 | |||
| 85 | if (n > _max_factorial) { | ||
| 86 | LOG("Error: won't compute 'permtoindex()' for n=%" PRId64 | ||
| 87 | " because it is larger than %" PRId64 "\n", | ||
| 88 | n, _max_factorial); | ||
| 89 | goto indextoperm_error; | ||
| 90 | } | ||
| 91 | |||
| 92 | memset(a, 0, n); | ||
| 93 | |||
| 94 | if (p < 0 || p >= factorial(n)) | ||
| 95 | goto indextoperm_error; | ||
| 96 | |||
| 97 | for (i = 0; i < n; i++) { | ||
| 98 | for (j = 0, c = 0; c <= p / factorial(n-i-1); j++) | ||
| 99 | c += a[j] ? 0 : 1; | ||
| 100 | r[i] = j-1; | ||
| 101 | a[j-1] = 1; | ||
| 102 | p %= factorial(n-i-1); | ||
| 103 | } | ||
| 104 | |||
| 105 | if (!isperm(r, n)) | ||
| 106 | goto indextoperm_error; | ||
| 107 | |||
| 108 | return; | ||
| 109 | |||
| 110 | indextoperm_error: | ||
| 111 | memset(r, _error, n); | ||
| 112 | } | ||
| 113 | |||
| 114 | _static int | ||
| 115 | permsign(uint8_t *a, int64_t n) | ||
| 116 | { | ||
| 117 | int i, j; | ||
| 118 | uint8_t ret; | ||
| 119 | |||
| 120 | for (i = 0, ret = 0; i < n; i++) | ||
| 121 | for (j = i+1; j < n; j++) | ||
| 122 | ret += a[i] > a[j] ? 1 : 0; | ||
| 123 | |||
| 124 | return ret % 2; | ||
| 125 | } | ||
