#include <iostream>
#include <array>
#include <vector>
#include <cmath>
#include <stdexcept>
/**
* Computes the pseudo-fusion value of a window of sensor readings.
*
* The window contains N values aggregated from 4 sensor streams.
* The fusion is computed as the geometric mean:
* result = (x1 * x2 * ... * xN) ^ (1/N)
*
* To avoid overflow from direct multiplication, we use the log-sum-exp trick:
* result = exp((1/N) * sum(log(xi)))
*
* @param window Flat array of N aggregated sensor values (each aggregated from 4 streams)
* @return The pseudo-fusion value (geometric mean)
*/
double computePseudoFusion(const std::vector<double>& window) {
const size_t N = window.size();
if (N <= 0) {
throw std::invalid_argument("Window must contain at least one value.");
}
double log_sum = 0.0;
for (size_t i = 0; i < N; i++) {
if (window[i] <= 0.0) {
throw std::domain_error(
"All sensor values must be positive for geometric mean computation. "
"Got non-positive value at index " + std::to_string(i)
);
}
log_sum += std::log(window[i]);
}
return std::exp(log_sum / static_cast<double>(N));
}
int main() {
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8YXJyYXk+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxjbWF0aD4KI2luY2x1ZGUgPHN0ZGV4Y2VwdD4KCi8qKgogKiBDb21wdXRlcyB0aGUgcHNldWRvLWZ1c2lvbiB2YWx1ZSBvZiBhIHdpbmRvdyBvZiBzZW5zb3IgcmVhZGluZ3MuCiAqCiAqIFRoZSB3aW5kb3cgY29udGFpbnMgTiB2YWx1ZXMgYWdncmVnYXRlZCBmcm9tIDQgc2Vuc29yIHN0cmVhbXMuCiAqIFRoZSBmdXNpb24gaXMgY29tcHV0ZWQgYXMgdGhlIGdlb21ldHJpYyBtZWFuOgogKiAgIHJlc3VsdCA9ICh4MSAqIHgyICogLi4uICogeE4pIF4gKDEvTikKICoKICogVG8gYXZvaWQgb3ZlcmZsb3cgZnJvbSBkaXJlY3QgbXVsdGlwbGljYXRpb24sIHdlIHVzZSB0aGUgbG9nLXN1bS1leHAgdHJpY2s6CiAqICAgcmVzdWx0ID0gZXhwKCgxL04pICogc3VtKGxvZyh4aSkpKQogKgogKiBAcGFyYW0gd2luZG93ICBGbGF0IGFycmF5IG9mIE4gYWdncmVnYXRlZCBzZW5zb3IgdmFsdWVzIChlYWNoIGFnZ3JlZ2F0ZWQgZnJvbSA0IHN0cmVhbXMpCiAqIEByZXR1cm4gICAgICAgIFRoZSBwc2V1ZG8tZnVzaW9uIHZhbHVlIChnZW9tZXRyaWMgbWVhbikKICovCmRvdWJsZSBjb21wdXRlUHNldWRvRnVzaW9uKGNvbnN0IHN0ZDo6dmVjdG9yPGRvdWJsZT4mIHdpbmRvdykgewogICAgY29uc3Qgc2l6ZV90IE4gPSB3aW5kb3cuc2l6ZSgpOwoKICAgIGlmIChOIDw9IDApIHsKICAgICAgICB0aHJvdyBzdGQ6OmludmFsaWRfYXJndW1lbnQoIldpbmRvdyBtdXN0IGNvbnRhaW4gYXQgbGVhc3Qgb25lIHZhbHVlLiIpOwogICAgfQoKICAgIGRvdWJsZSBsb2dfc3VtID0gMC4wOwoKICAgIGZvciAoc2l6ZV90IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgaWYgKHdpbmRvd1tpXSA8PSAwLjApIHsKICAgICAgICAgICAgdGhyb3cgc3RkOjpkb21haW5fZXJyb3IoCiAgICAgICAgICAgICAgICAiQWxsIHNlbnNvciB2YWx1ZXMgbXVzdCBiZSBwb3NpdGl2ZSBmb3IgZ2VvbWV0cmljIG1lYW4gY29tcHV0YXRpb24uICIKICAgICAgICAgICAgICAgICJHb3Qgbm9uLXBvc2l0aXZlIHZhbHVlIGF0IGluZGV4ICIgKyBzdGQ6OnRvX3N0cmluZyhpKQogICAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBsb2dfc3VtICs9IHN0ZDo6bG9nKHdpbmRvd1tpXSk7CiAgICB9CgogICAgcmV0dXJuIHN0ZDo6ZXhwKGxvZ19zdW0gLyBzdGF0aWNfY2FzdDxkb3VibGU+KE4pKTsKfQoKaW50IG1haW4oKSB7CgkKCn0=