aboutsummaryrefslogtreecommitdiff
path: root/src/utils/math.h
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2024-08-18 14:26:45 +0200
committerSebastiano Tronto <sebastiano@tronto.net>2024-08-18 14:26:45 +0200
commit18c9a8b8905304cf5f8fc15825769046a3144866 (patch)
treea7807bb32b0a5d9ded7d3cedccc598f64a9b00fe /src/utils/math.h
parentf25a10e19eca294c4e6a99e4f80ce5cfd11a0e5f (diff)
downloadnissy-core-18c9a8b8905304cf5f8fc15825769046a3144866.tar.gz
nissy-core-18c9a8b8905304cf5f8fc15825769046a3144866.zip
Reorganized folder structure
Diffstat (limited to 'src/utils/math.h')
-rw-r--r--src/utils/math.h185
1 files changed, 185 insertions, 0 deletions
diff --git a/src/utils/math.h b/src/utils/math.h
new file mode 100644
index 0000000..87402e6
--- /dev/null
+++ b/src/utils/math.h
@@ -0,0 +1,185 @@
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
5_static int64_t factorial(int64_t);
6_static bool isperm(uint8_t *, int64_t);
7_static int64_t permtoindex(uint8_t *, int64_t);
8_static void indextoperm(int64_t, int64_t, uint8_t *);
9_static int permsign(uint8_t *, int64_t);
10_static int64_t digitstosumzero(uint8_t *, uint8_t, uint8_t);
11_static void sumzerotodigits(int64_t, uint8_t, uint8_t, uint8_t *);
12
13_static int64_t
14factorial(int64_t n)
15{
16 int64_t i, ret;
17
18 if (n > _max_factorial) {
19 LOG("Error: won't compute factorial for n=%" PRId64 " because"
20 " it is larger than %" PRId64 "\n", n, _max_factorial);
21 return -1;
22 }
23
24 if (n < 0)
25 return 0;
26
27 for (i = 1, ret = 1; i <= n; i++)
28 ret *= i;
29
30 return ret;
31}
32
33_static bool
34isperm(uint8_t *a, int64_t n)
35{
36 int64_t i;
37 bool aux[_max_factorial+1];
38
39 if (n > _max_factorial) {
40 LOG("Error: won't compute 'isperm()' for n=%" PRId64 " because"
41 " it is larger than %" PRId64 "\n", n, _max_factorial);
42 return false;
43 }
44
45 memset(aux, false, n);
46
47 for (i = 0; i < n; i++) {
48 if (a[i] >= n)
49 return false;
50 else
51 aux[a[i]] = true;
52 }
53
54 for (i = 0; i < n; i++)
55 if (!aux[i])
56 return false;
57
58 return true;
59}
60
61_static int64_t
62permtoindex(uint8_t *a, int64_t n)
63{
64 int64_t i, j, c, ret;
65
66 if (n > _max_factorial) {
67 LOG("Error: won't compute 'permtoindex()' for n=%" PRId64
68 " because it is larger than %" PRId64 "\n",
69 n, _max_factorial);
70 return -1;
71 }
72
73 if (!isperm(a, n))
74 return -1;
75
76 for (i = 0, ret = 0; i < n; i++) {
77 for (j = i+1, c = 0; j < n; j++)
78 c += (a[i] > a[j]) ? 1 : 0;
79 ret += factorial(n-i-1) * c;
80 }
81
82 return ret;
83}
84
85_static void
86indextoperm(int64_t p, int64_t n, uint8_t *r)
87{
88 int64_t i, j, c;
89 uint8_t a[_max_factorial+1];
90
91 if (n > _max_factorial) {
92 LOG("Error: won't compute 'permtoindex()' for n=%" PRId64
93 " because it is larger than %" PRId64 "\n",
94 n, _max_factorial);
95 goto indextoperm_error;
96 }
97
98 memset(a, 0, n);
99
100 if (p < 0 || p >= factorial(n))
101 goto indextoperm_error;
102
103 for (i = 0; i < n; i++) {
104 for (j = 0, c = 0; c <= p / factorial(n-i-1); j++)
105 c += a[j] ? 0 : 1;
106 r[i] = j-1;
107 a[j-1] = 1;
108 p %= factorial(n-i-1);
109 }
110
111 if (!isperm(r, n))
112 goto indextoperm_error;
113
114 return;
115
116indextoperm_error:
117 memset(r, _error, n);
118}
119
120_static int
121permsign(uint8_t *a, int64_t n)
122{
123 int i, j;
124 uint8_t ret;
125
126 for (i = 0, ret = 0; i < n; i++)
127 for (j = i+1; j < n; j++)
128 ret += a[i] > a[j] ? 1 : 0;
129
130 return ret % 2;
131}
132
133_static int64_t
134digitstosumzero(uint8_t *a, uint8_t n, uint8_t b)
135{
136 int64_t ret, p;
137 uint8_t i, sum;
138
139 if (!((n == 8 && b == 3 ) || (n == 12 && b == 2))) {
140 LOG("Won't compute 'sumzero' for n=%" PRIu8 "and b=%" PRIu8
141 " (use n=8 b=3 or n=12 b=2)\n", n, b);
142 return -1;
143 }
144
145 for (i = 1, ret = 0, p = 1, sum = 0; i < n; i++, p *= (int64_t)b) {
146 if (a[i] >= b) {
147 LOG("Error: digit %" PRIu8 " larger than maximum"
148 " (b=%" PRIu8 "\n", a[i], b);
149 return -1;
150 }
151 sum += a[i];
152 ret += p * (int64_t)a[i];
153 }
154
155 if ((sum + a[0]) % b != 0) {
156 LOG("Error: digits do not have sum zero modulo b\n");
157 return -1;
158 }
159
160 return ret;
161}
162
163_static void
164sumzerotodigits(int64_t d, uint8_t n, uint8_t b, uint8_t *a)
165{
166 uint8_t sum;
167 int64_t i;
168
169 if (!((n == 8 && b == 3 ) || (n == 12 && b == 2))) {
170 LOG("Won't compute 'digits' for n=%" PRIu8 "and b=%" PRIu8
171 " (use n=8 b=3 or n=12 b=2)\n");
172 goto digitstosumzero_error;
173 }
174
175 for (i = 1, sum = 0; i < n; i++, d /= (int64_t)b) {
176 a[i] = (uint8_t)(d % (int64_t)b);
177 sum += a[i];
178 }
179 a[0] = (b - (sum % b)) % b;
180
181 return;
182
183digitstosumzero_error:
184 memset(a, _error, n);
185}

Generated with cgit - Back to sebastiano.tronto.net