Efficient computation of dot product of convolutions I have two FIR filters $f_{1},f_{2}$ and two short time-slices of signals $s_{1},s_{2}$. I need to compute: $$\left&lt;s_{1}*f_{1},\ s_{2}*f_{2}\right&gt;$$

Which I compute using six FFTs: each $s_{i}*f_{i}$ is computed by pointwise multiplication of the (padded) FFT vector of $s_{i}$ by the corresponding FFT of $f_{i}$, then an IFFT is computed and the result is truncated (this truncation is the reason computing the dot product in the frequency domain does not work).

The $f_{i}$ are known ahead of time, so this takes four FFTs at each iteration of my code.

Is there a way to get away with computing less? If the conjugate transpose of $f_{1}$ could be composed on $f_{2}$ and a FIR filter was the result, it would be posible to manage with just 2 FFTs with something like: $$IFFT\left(FFT(s_{2})\cdot FFT(f_{2}^T\circ f_{1})\right)$$

(where $FFT(f_{2}^T\circ f_{1})$ is computed ahead of time,) but this doesn't quite seem to work out.

A team member of mine asked a similar question (on another stackexchange community) but did not get helpful replies.

edit (details about truncation in my code):

To compute $\left&lt;s*f\right&gt;$ (supposing that $s$ is of length 20000 and $f$ of length 4000, though these numbers are made up)  both vectors are zero-padded to length $20000+4000-1$, FFTs are multiplied pointwise, IFFT is computed on the product, and the samples in indices $\left[3999, 19998\right]$ are taken from the result (this represents a closed range of indices on a vector indexed from 0.)

This gives us all of the "meaningful" result computable from the slice of the signal: all dot products between $f$ and a shift of the signal-slice $s$ such that $f$ is shifted onto a completely-known part of $s$ (this is done over successive time slices of a signal as it is recorded.) It's important to notice the result is of length 16000 (the length of $s$ minus the length of $f$).
Convolution is a specific type of linear operator. So in all generality, you can write your expression as $\langle F_1 s_1 | F_2 s_2 \rangle$ with two linear operators $F_{1,2}$. Using the rules of operators in bilinear forms, we can rewrite this as $\langle s_1|F_1^\dagger F_2 |s_2\rangle$ and that again as $\langle s_1|\left(F_1^\dagger F_2\right) s_2\rangle$.

In your case, the two operators have a pleasant property. They are toeplitz, and if we take your padding into account, even circulant. The product of two circulant operators is again circulant, as is the conjugate transpose. That means you can write the result of the operator product as a single convolution. Your convolution kernel is the correlation product $\mathrm{corr}({f_1}^*,f_2)$. 

If you implement this using fast convolution, you need to pad this correlation product and the size of your kernel will increase to the sum of the sizes of $f_{1,2}$. Accordingly, the required padding for $s_2$ will also increase.