XOR, AND and OR convolutions on arrays of size all follow the same recipe as FFT: transform, multiply pointwise, inverse transform, in . Subset (disjoint-union) convolution is in SOS DP.
The three transforms
All three are in-place butterflies on pairs :
| Convolution | Forward | Inverse |
|---|---|---|
| XOR | same, then divide by | |
| OR | ||
| AND |
template<class T> void fwht(vector<T>& a, bool inv, int type) { // type: 0 xor, 1 or, 2 and
int N = a.size();
for (int len = 1; len < N; len <<= 1)
for (int i = 0; i < N; i += 2 * len)
for (int j = i; j < i + len; j++) {
T u = a[j], v = a[j + len];
if (type == 0) a[j] = u + v, a[j + len] = u - v;
else if (type == 1) a[j + len] = inv ? v - u : v + u;
else a[j] = inv ? u - v : u + v;
}
if (type == 0 && inv) { T k = T(1) / T(N); for (auto& x : a) x *= k; } // modular: multiply by inverse of N
}
// c = a (*) b: fwht(a,0,t); fwht(b,0,t); c[i] = a[i]*b[i]; fwht(c,1,t);OR and AND are the subset and superset zeta/Möbius transforms. XOR is the Walsh-Hadamard transform — the direct analogue of FFT over instead of complex roots of unity. Its coefficients are exactly the Fourier spectrum of a Boolean function over (the basis of Boolean function analysis and Reed-Muller code decoding), beyond CP but worth knowing where the name comes from:
Proof: the three butterflies compute the right transform, and the inverses recover the input
XOR (Walsh-Hadamard). By induction on : for the transform is the identity, matching . Splitting a size- array into first/second halves of size , running the inductive transform on each half independently (this is exactly what the level-by-level loop does: at level -size the recursion has already combined everything below that size within each half) gives and ; the final butterfly on corresponding entries is exactly the block matrix H_n=\begin{psmallmatrix}H_{n-1}&H_{n-1}\\H_{n-1}&-H_{n-1}\end{psmallmatrix} applied to the concatenation, by direct expansion of the block product. So the butterfly computes for all . Since is symmetric with (each diagonal entry of sums , and each off-diagonal entry is which is by pairing for any bit where differ), running the same butterfly again and dividing by recovers exactly, so transform-multiply-inverse computes , and since pointwise (the defining property of the XOR character being multiplicative under XOR convolution), this is exactly the XOR convolution of . OR/AND. The OR butterfly applied bit-by-bit across all levels is literally the subset-zeta dimension sweep from SOS DP (there proved to compute ) — the butterfly’s pairing of indices differing in bit within blocks of size is the same pairing the sweep uses, just phrased with explicit
lendoubling instead of an explicit bit index. Its stated inverse undoes each addition exactly, recovering . The pointwise product of two subset-zeta transforms, Möbius-inverted, is the OR convolution by the same argument as the zeta/Möbius proof in SOS DP (restricted to , i.e. no popcount ranking, so overlaps are allowed — matching the OR convolution’s definition, which permits ). The AND case is the mirror image (superset sums) by symmetry under bit complementation.Tested: all three butterflies (XOR/OR/AND), each transform→pointwise-multiply→inverse pipeline, checked against the direct definition of the respective convolution for up to 6, random
doublearrays, matching to .
Using the transform structure
The transform of a single “indicator” is everywhere: . So products of many sparse factors can be computed in the transform domain without convolving them one by one.
Count subsets with XOR , or choose one element from each of groups: for “pick any subset of ”, the product is . In the transform domain each factor is . So if every has even overlap with , else 0. (The rank of an XOR basis gives the same answer: subsets per reachable value.)
Product of factors where each transform takes only two values or : for each , count how many factors take the “minus” value. Let be that count; then over the “plus” factors times the “minus” factors. Counting for all needs one more transform of the sum of the indicators: . This is the classic trick for “each of triples, choose one value, count XOR outcomes” in (CF 1119H “Triple”): with three values per group, solve a small linear system for the number of groups in each sign pattern.
Repeated self-convolution: is pointwise , so “XOR of independent choices” costs one transform plus fast powers.
Rank and linear algebra: the support of the transform of the indicator of a linear subspace is its orthogonal complement . That links XOR transforms to XOR bases (XOR Basis).
Variants
- Modular arithmetic: the XOR inverse divides by ; multiply by its modular inverse (needs an odd modulus).
- Floating point: fine for probabilities. Use
doubleand divide by at the end. - Base- “XOR” (digit-wise addition mod ): use the -point DFT on each digit (roots of unity mod when , or an extension ring). For the transform uses with .
- Max-plus “OR convolution” (): no fast transform in general. If is monotone, zeta with max then split as needed; otherwise subset enumeration in .
- GCD and LCM convolutions on : the same idea on the divisor lattice. “Sum over multiples” (zeta) and Möbius over divisors give in with a prime-by-prime sweep (Möbius).
Uses
| Problem | Convolution |
|---|---|
| number of pairs with for every | XOR self-convolution of frequencies |
| Nim: probability the XOR of random piles is 0 | XOR power of the pile distribution |
| count pairs with | OR convolution |
| expected value of AND of random picks | AND convolution |
| ”choose one of three values in each group, count XOR results” | transform-domain counting (above) |
| game sums: distribution of Grundy XOR | XOR convolution |