void principalFFT(float *features, float *fft) {
    // apply principal FFT (naive implementation for the top N frequencies only)
    const int topFrequencies[] = { {{ f.to_array(fft.idx, True) }} };

    {% if lookup_cos %}
        {% with op="cos" %}
            {% include "principalfft/lut.jinja" %}
        {% endwith %}

        {# sin lookup is available only if cos lookup is used #}
        {% if lookup_sin %}
            {% with op="sin" %}
                {% include "principalfft/lut.jinja" %}
            {% endwith %}
        {% else %}
            {% with op="sin" %}
                {% include "principalfft/lut_bool.jinja" %}
            {% endwith %}
        {% endif %}
    {% endif %}

    for (int i = 0; i < {{ size }}; i++) {
        const int k = topFrequencies[i];
        {% if not lookup_cos %}
            const float harmonic = {{ 2 * PI / fft.original_size }} * k;
        {% endif %}
        float re = 0;
        float im = 0;

        // optimized case
        if (k == 0) {
            for (int n = 0; n < {{ fft.original_size }}; n++) {
                re += features[n];
            }
        }
        else {
            for (int n = 0; n < {{ fft.original_size }}; n++) {
                {% if lookup_cos %}
                    const float cos_n = cosLUT[i][n];

                    {% if lookup_sin %}
                        const float sin_n = sinLUT[i][n];
                    {% else %}
                        const float sin_n = sinLUT[i][n] * sqrt(1 - cos_n * cos_n);
                    {% endif %}
                {% else %}
                    const float harmonicN = harmonic * n;
                    const float cos_n = cos(harmonicN);
                    const float sin_n = sin(harmonicN);
                {% endif %}

                re += features[n] * cos_n;
                im -= features[n] * sin_n;
            }
        }

        fft[i] = sqrt(re * re + im * im);
    }
}