math.h (3958B)
1 #define SWAP(x, y) do { x ^= y; y ^= x; x ^= y; } while (0) 2 #define MIN(x, y) ((x) < (y) ? (x) : (y)) 3 #define MAX(x, y) ((x) > (y) ? (x) : (y)) 4 #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) 5 6 STATIC int64_t factorial(int64_t); 7 STATIC bool isperm(size_t n, const uint8_t [n]); 8 STATIC int64_t permtoindex(size_t n, const uint8_t [n]); 9 STATIC void indextoperm(int64_t, size_t n, uint8_t [n]); 10 STATIC int permsign(size_t n, const uint8_t [n]); 11 STATIC int64_t digitstosumzero(size_t n, const uint8_t [n], uint8_t); 12 STATIC void sumzerotodigits(int64_t, size_t n, uint8_t, uint8_t [n]); 13 STATIC double intpow(double, uint64_t); 14 15 STATIC int64_t 16 factorial(int64_t n) 17 { 18 int64_t i, ret; 19 20 if (n > FACTORIAL_MAX) { 21 LOG("Error: won't compute factorial for n=%" PRId64 " because" 22 " it is larger than %" PRId64 "\n", n, FACTORIAL_MAX); 23 return -1; 24 } 25 26 if (n < 0) 27 return 0; 28 29 for (i = 1, ret = 1; i <= n; i++) 30 ret *= i; 31 32 return ret; 33 } 34 35 STATIC bool 36 isperm(size_t n, const uint8_t a[n]) 37 { 38 size_t i; 39 bool aux[FACTORIAL_MAX+1]; 40 41 if (n > (size_t)FACTORIAL_MAX) { 42 LOG("Error: won't compute 'isperm()' for n=%zu because" 43 " it is larger than %" PRId64 "\n", n, FACTORIAL_MAX); 44 return false; 45 } 46 47 memset(aux, false, n); 48 49 for (i = 0; i < n; i++) { 50 if (a[i] >= n) 51 return false; 52 else 53 aux[a[i]] = true; 54 } 55 56 for (i = 0; i < n; i++) 57 if (!aux[i]) 58 return false; 59 60 return true; 61 } 62 63 STATIC int64_t 64 permtoindex(size_t n, const uint8_t a[n]) 65 { 66 size_t i, j; 67 int64_t c, ret; 68 69 if (n > (size_t)FACTORIAL_MAX) { 70 LOG("Error: won't compute 'permtoindex()' for n=%zu because " 71 "it is larger than %" PRId64 "\n", n, FACTORIAL_MAX); 72 return -1; 73 } 74 75 if (!isperm(n, a)) 76 return -1; 77 78 for (i = 0, ret = 0; i < n; i++) { 79 for (j = i+1, c = 0; j < n; j++) 80 c += (a[i] > a[j]) ? 1 : 0; 81 ret += factorial(n-i-1) * c; 82 } 83 84 return ret; 85 } 86 87 STATIC void 88 indextoperm(int64_t p, size_t n, uint8_t r[n]) 89 { 90 int64_t c; 91 size_t i, j; 92 uint8_t a[FACTORIAL_MAX+1]; 93 94 if (n > FACTORIAL_MAX) { 95 LOG("Error: won't compute 'indextoperm()' for n=%zu because " 96 "it is larger than %" PRId64 "\n", n, FACTORIAL_MAX); 97 goto indextoperm_error; 98 } 99 100 memset(a, 0, n); 101 102 if (p < 0 || p >= factorial(n)) 103 goto indextoperm_error; 104 105 for (i = 0; i < n; i++) { 106 for (j = 0, c = 0; c <= p / factorial(n-i-1); j++) 107 c += a[j] ? 0 : 1; 108 r[i] = j-1; 109 a[j-1] = 1; 110 p %= factorial(n-i-1); 111 } 112 113 if (!isperm(n, r)) 114 goto indextoperm_error; 115 116 return; 117 118 indextoperm_error: 119 memset(r, UINT8_ERROR, n); 120 } 121 122 STATIC int 123 permsign(size_t n, const uint8_t a[n]) 124 { 125 size_t i, j, ret; 126 127 for (i = 0, ret = 0; i < n; i++) 128 for (j = i+1; j < n; j++) 129 ret += a[i] > a[j] ? 1 : 0; 130 131 return ret % 2; 132 } 133 134 STATIC int64_t 135 digitstosumzero(size_t n, const uint8_t a[n], uint8_t b) 136 { 137 int64_t ret, p; 138 size_t i, sum; 139 140 if (!((n == 8 && b == 3 ) || (n == 12 && b == 2))) { 141 LOG("Won't compute 'sumzero' for n=%zu and b=%" PRIu8 142 " (use n=8 b=3 or n=12 b=2)\n", n, b); 143 return -1; 144 } 145 146 for (i = 1, ret = 0, p = 1, sum = 0; i < n; i++, p *= (int64_t)b) { 147 if (a[i] >= b) { 148 LOG("Error: digit %" PRIu8 " larger than maximum" 149 " (b=%" PRIu8 "\n", a[i], b); 150 return -1; 151 } 152 sum += a[i]; 153 ret += p * (int64_t)a[i]; 154 } 155 156 if ((sum + a[0]) % b != 0) { 157 LOG("Error: digits do not have sum zero modulo b\n"); 158 return -1; 159 } 160 161 return ret; 162 } 163 164 STATIC void 165 sumzerotodigits(int64_t d, size_t n, uint8_t b, uint8_t a[n]) 166 { 167 uint8_t sum; 168 size_t i; 169 170 if (!((n == 8 && b == 3 ) || (n == 12 && b == 2))) { 171 LOG("Won't compute 'digits' for n=%" PRIu8 "and b=%" PRIu8 172 " (use n=8 b=3 or n=12 b=2)\n"); 173 goto sumzerotodigits_error; 174 } 175 176 for (i = 1, sum = 0; i < n; i++, d /= (int64_t)b) { 177 a[i] = (uint8_t)(d % (int64_t)b); 178 sum += a[i]; 179 } 180 a[0] = (b - (sum % b)) % b; 181 182 return; 183 184 sumzerotodigits_error: 185 memset(a, UINT8_ERROR, n); 186 } 187 188 STATIC double 189 intpow(double b, uint64_t e) 190 { 191 double r; 192 193 if (e == 0) 194 return 1; 195 196 r = intpow(b, e/2); 197 198 return e % 2 == 0 ? r * r : b * r * r; 199 }