summaryrefslogtreecommitdiff
path: root/content/math/transforms
diff options
context:
space:
mode:
authorGloria Mundi <gloria@gloria-mundi.eu>2024-11-16 01:24:14 +0100
committerGloria Mundi <gloria@gloria-mundi.eu>2024-11-16 01:24:14 +0100
commit98567ec798aa8ca2cfbcb85c774dd470f30e30d4 (patch)
tree5113d5cc24d1ad5f93810b6442ce584a36950dc8 /content/math/transforms
parentad3856a6b766087df0036de0b556f4700a6498c9 (diff)
parent8d11c6c8213f46f0fa19826917c255edd5d43cb1 (diff)
mzuenni tests
Diffstat (limited to 'content/math/transforms')
-rw-r--r--content/math/transforms/andTransform.cpp8
-rw-r--r--content/math/transforms/bitwiseTransforms.cpp12
-rw-r--r--content/math/transforms/fft.cpp23
-rw-r--r--content/math/transforms/fftMul.cpp15
-rw-r--r--content/math/transforms/multiplyBitwise.cpp8
-rw-r--r--content/math/transforms/multiplyFFT.cpp12
-rw-r--r--content/math/transforms/multiplyNTT.cpp8
-rw-r--r--content/math/transforms/ntt.cpp23
-rw-r--r--content/math/transforms/orTransform.cpp8
-rw-r--r--content/math/transforms/seriesOperations.cpp56
-rw-r--r--content/math/transforms/xorTransform.cpp10
11 files changed, 183 insertions, 0 deletions
diff --git a/content/math/transforms/andTransform.cpp b/content/math/transforms/andTransform.cpp
new file mode 100644
index 0000000..1fd9f5c
--- /dev/null
+++ b/content/math/transforms/andTransform.cpp
@@ -0,0 +1,8 @@
+void fft(vector<ll>& a, bool inv = false) {
+ int n = sz(a);
+ for (int s = 1; s < n; s *= 2) {
+ for (int i = 0; i < n; i += 2 * s) {
+ for (int j = i; j < i + s; j++) {
+ ll& u = a[j], &v = a[j + s];
+ tie(u, v) = inv ? pair(v - u, u) : pair(v, u + v);
+}}}}
diff --git a/content/math/transforms/bitwiseTransforms.cpp b/content/math/transforms/bitwiseTransforms.cpp
new file mode 100644
index 0000000..28561da
--- /dev/null
+++ b/content/math/transforms/bitwiseTransforms.cpp
@@ -0,0 +1,12 @@
+void bitwiseConv(vector<ll>& a, bool inv = false) {
+ int n = sz(a);
+ for (int s = 1; s < n; s *= 2) {
+ for (int i = 0; i < n; i += 2 * s) {
+ for (int j = i; j < i + s; j++) {
+ ll& u = a[j], &v = a[j + s];
+ tie(u, v) = inv ? pair(v - u, u) : pair(v, u + v); // AND
+ //tie(u, v) = inv ? pair(v, u - v) : pair(u + v, u); //OR
+ //tie(u, v) = pair(u + v, u - v); // XOR
+ }}}
+ //if (inv) for (ll& x : a) x /= n; // XOR (careful with MOD)
+}
diff --git a/content/math/transforms/fft.cpp b/content/math/transforms/fft.cpp
new file mode 100644
index 0000000..2bd95b2
--- /dev/null
+++ b/content/math/transforms/fft.cpp
@@ -0,0 +1,23 @@
+using cplx = complex<double>;
+
+void fft(vector<cplx>& a, bool inv = false) {
+ int n = sz(a);
+ for (int i = 0, j = 1; j < n - 1; ++j) {
+ for (int k = n >> 1; k > (i ^= k); k >>= 1);
+ if (j < i) swap(a[i], a[j]);
+ }
+ static vector<cplx> ws(2, 1);
+ for (static int k = 2; k < n; k *= 2) {
+ ws.resize(n);
+ cplx w = polar(1.0, acos(-1.0) / k);
+ for (int i=k; i<2*k; i++) ws[i] = ws[i/2] * (i % 2 ? w : 1);
+ }
+ for (int s = 1; s < n; s *= 2) {
+ for (int j = 0; j < n; j += 2 * s) {
+ for (int k = 0; k < s; k++) {
+ cplx u = a[j + k], t = a[j + s + k];
+ t *= (inv ? conj(ws[s + k]) : ws[s + k]);
+ a[j + k] = u + t;
+ a[j + s + k] = u - t;
+ if (inv) a[j + k] /= 2, a[j + s + k] /= 2;
+}}}}
diff --git a/content/math/transforms/fftMul.cpp b/content/math/transforms/fftMul.cpp
new file mode 100644
index 0000000..660ed79
--- /dev/null
+++ b/content/math/transforms/fftMul.cpp
@@ -0,0 +1,15 @@
+vector<cplx> mul(vector<ll>& a, vector<ll>& b) {
+ int n = 1 << (__lg(sz(a) + sz(b) - 1) + 1);
+ vector<cplx> c(all(a)), d(n);
+ c.resize(n);
+ for (int i = 0; i < sz(b); i++) c[i] = {real(c[i]), b[i]};
+ fft(c);
+ for (int i = 0; i < n; i++) {
+ int j = (n - i) & (n - 1);
+ cplx x = (c[i] + conj(c[j])) / cplx{2, 0}; //fft(a)[i];
+ cplx y = (c[i] - conj(c[j])) / cplx{0, 2}; //fft(b)[i];
+ d[i] = x * y;
+ }
+ fft(d, true);
+ return d;
+}
diff --git a/content/math/transforms/multiplyBitwise.cpp b/content/math/transforms/multiplyBitwise.cpp
new file mode 100644
index 0000000..f7cf169
--- /dev/null
+++ b/content/math/transforms/multiplyBitwise.cpp
@@ -0,0 +1,8 @@
+vector<ll> mul(vector<ll> a, vector<ll> b) {
+ int n = 1 << (__lg(2 * max(sz(a), sz(b)) - 1));
+ a.resize(n), b.resize(n);
+ bitwiseConv(a), bitwiseConv(b);
+ for (int i=0; i<n; i++) a[i] *= b[i]; // MOD?
+ bitwiseConv(a, true);
+ return a;
+}
diff --git a/content/math/transforms/multiplyFFT.cpp b/content/math/transforms/multiplyFFT.cpp
new file mode 100644
index 0000000..0022d1f
--- /dev/null
+++ b/content/math/transforms/multiplyFFT.cpp
@@ -0,0 +1,12 @@
+vector<ll> mul(vector<ll>& a, vector<ll>& b) {
+ int n = 1 << (__lg(sz(a) + sz(b) - 1) + 1);
+ vector<cplx> a2(all(a)), b2(all(b));
+ a2.resize(n), b2.resize(n);
+ fft(a2), fft(b2);
+ for (int i=0; i<n; i++) a2[i] *= b2[i];
+ fft(a2, true);
+
+ vector<ll> ans(n);
+ for (int i=0; i<n; i++) ans[i] = llround(a2[i].real());
+ return ans;
+}
diff --git a/content/math/transforms/multiplyNTT.cpp b/content/math/transforms/multiplyNTT.cpp
new file mode 100644
index 0000000..806d124
--- /dev/null
+++ b/content/math/transforms/multiplyNTT.cpp
@@ -0,0 +1,8 @@
+vector<ll> mul(vector<ll> a, vector<ll> b) {
+ int n = 1 << (__lg(sz(a) + sz(b) - 1) + 1);
+ a.resize(n), b.resize(n);
+ ntt(a), ntt(b);
+ for (int i=0; i<n; i++) a[i] = a[i] * b[i] % mod;
+ ntt(a, true);
+ return a;
+}
diff --git a/content/math/transforms/ntt.cpp b/content/math/transforms/ntt.cpp
new file mode 100644
index 0000000..ca605d3
--- /dev/null
+++ b/content/math/transforms/ntt.cpp
@@ -0,0 +1,23 @@
+constexpr ll mod = 998244353, root = 3;
+
+void ntt(vector<ll>& a, bool inv = false) {
+ int n = sz(a);
+ auto b = a;
+ ll r = inv ? powMod(root, mod - 2, mod) : root;
+
+ for (int s = n / 2; s > 0; s /= 2) {
+ ll ws = powMod(r, (mod - 1) / (n / s), mod), w = 1;
+ for (int j = 0; j < n / 2; j += s) {
+ for (int k = j; k < j + s; k++) {
+ ll u = a[j + k], t = a[j + s + k] * w % mod;
+ b[k] = (u + t) % mod;
+ b[n/2 + k] = (u - t + mod) % mod;
+ }
+ w = w * ws % mod;
+ }
+ swap(a, b);
+ }
+ if (inv) {
+ ll div = powMod(n, mod - 2, mod);
+ for (auto& x : a) x = x * div % mod;
+}}
diff --git a/content/math/transforms/orTransform.cpp b/content/math/transforms/orTransform.cpp
new file mode 100644
index 0000000..eb1da44
--- /dev/null
+++ b/content/math/transforms/orTransform.cpp
@@ -0,0 +1,8 @@
+void fft(vector<ll>& a, bool inv = false) {
+ int n = sz(a);
+ for (int s = 1; s < n; s *= 2) {
+ for (int i = 0; i < n; i += 2 * s) {
+ for (int j = i; j < i + s; j++) {
+ ll& u = a[j], &v = a[j + s];
+ tie(u, v) = inv ? pair(v, u - v) : pair(u + v, u);
+}}}}
diff --git a/content/math/transforms/seriesOperations.cpp b/content/math/transforms/seriesOperations.cpp
new file mode 100644
index 0000000..4743674
--- /dev/null
+++ b/content/math/transforms/seriesOperations.cpp
@@ -0,0 +1,56 @@
+vector<ll> poly_inv(const vector<ll>& a, int n) {
+ vector<ll> q = {powMod(a[0], mod-2, mod)};
+ for (int len = 1; len < n; len *= 2){
+ vector<ll> a2 = a, q2 = q;
+ a2.resize(2*len), q2.resize(2*len);
+ ntt(q2);
+ for (int j : {0, 1}) {
+ ntt(a2);
+ for (int i = 0; i < 2*len; i++) a2[i] = a2[i]*q2[i] % mod;
+ ntt(a2, true);
+ for (int i = 0; i < len; i++) a2[i] = 0;
+ }
+ for (int i = len; i < min(n, 2*len); i++) {
+ q.push_back((mod - a2[i]) % mod);
+ }}
+ return q;
+}
+
+vector<ll> poly_deriv(vector<ll> a) {
+ for (int i = 1; i < sz(a); i++)
+ a[i-1] = a[i] * i % mod;
+ a.pop_back();
+ return a;
+}
+
+vector<ll> poly_integr(vector<ll> a) {
+ if (a.empty()) return {0};
+ a.push_back(a.back() * powMod(sz(a), mod-2, mod) % mod);
+ for (int i = sz(a)-2; i > 0; i--)
+ a[i] = a[i-1] * powMod(i, mod-2, mod) % mod;
+ a[0] = 0;
+ return a;
+}
+
+vector<ll> poly_log(vector<ll> a, int n) {
+ a = mul(poly_deriv(a), poly_inv(a, n));
+ a.resize(n-1);
+ a = poly_integr(a);
+ return a;
+}
+
+vector<ll> poly_exp(vector<ll> a, int n) {
+ vector<ll> q = {1};
+ for (int len = 1; len < n; len *= 2) {
+ vector<ll> p = poly_log(q, 2*len);
+ for (int i = 0; i < 2*len; i++)
+ p[i] = (mod - p[i] + (i < sz(a) ? a[i] : 0)) % mod;
+ vector<ll> q2 = q;
+ q2.resize(2*len);
+ ntt(p), ntt(q2);
+ for (int i = 0; i < 2*len; i++) p[i] = p[i] * q2[i] % mod;
+ ntt(p, true);
+ for (int i = len; i < min(n, 2*len); i++) q.push_back(p[i]);
+ }
+ return q;
+}
diff --git a/content/math/transforms/xorTransform.cpp b/content/math/transforms/xorTransform.cpp
new file mode 100644
index 0000000..f9d1d82
--- /dev/null
+++ b/content/math/transforms/xorTransform.cpp
@@ -0,0 +1,10 @@
+void fft(vector<ll>& a, bool inv = false) {
+ int n = sz(a);
+ for (int s = 1; s < n; s *= 2) {
+ for (int i = 0; i < n; i += 2 * s) {
+ for (int j = i; j < i + s; j++) {
+ ll& u = a[j], &v = a[j + s];
+ tie(u, v) = pair(u + v, u - v);
+ }}}
+ if (inv) for (ll& x : a) x /= n;
+}