#ifndef MIX_HPP #define MIX_HPP #include // Use like `Householder::inPlace(data)` - size must be ≥ 1 template class Householder { static constexpr Sample multiplier{-2.0/size}; public: static void inPlace(Sample *arr) { double sum = 0; for (int i = 0; i < size; ++i) { sum += arr[i]; } sum *= multiplier; for (int i = 0; i < size; ++i) { arr[i] += sum; } }; }; // Use like `Hadamard::inPlace(data)` - size must be a power of 2 template class Hadamard { public: static inline void recursiveUnscaled(Sample * data) { if (size <= 1) { return; } constexpr int hSize = size/2; // Two (unscaled) Hadamards of half the size Hadamard::recursiveUnscaled(data); Hadamard::recursiveUnscaled(data + hSize); // Combine the two halves using sum/difference for (int i = 0; i < hSize; ++i) { double a = data[i]; double b = data[i + hSize]; data[i] = (a + b); data[i + hSize] = (a - b); } } static inline void inPlace(Sample * data) { recursiveUnscaled(data); Sample scalingFactor = std::sqrt(1.0/size); for (int c = 0; c < size; ++c) { data[c] *= scalingFactor; } } }; template class Shuffle { public: static inline void outOfPlace(T *in, T *out, const int *shuffle_spec) { for (int c=0; c < numCh; c++) { T sign = 1; int s = shuffle_spec[c]; if (s < 0) { sign = -1; s *= -1; } if (s >= numCh) { s = 0; } out[s] = sign * in[c]; } }; static inline void inPlace(T *data, const int *shuffle_spec) { T temp[numCh]; for (int c=0; c < numCh; c++) { temp[c] = data[c]; } Shuffle::outOfPlace(temp, data, shuffle_spec); }; }; #endif