Hello:
Posting this here as it seems germane to the forum and the version on Q&A forum not receiving response from XMOS.
The portion of the dsp_vector library that treats complex arithmetic requires real and imaginary parts in separate vectors. Yet the same library's FFT provides real and imaginary parts as elements of a structure, making the two portions, in a sense, incompatible. For instance, if I've read it correctly, a response to a related question (viewtopic.php?f=47&t=5199&p=26517&hilit=dsp_vector#p26517) suggests that users write their own routines for the dsp_vector library functions for this very reason.
I imagine almost all complex DSP is done on the results of FFTs, so am surprised these two libraries are not compatible.
Am I missing something? Is there an easy way to use these two libraries together? If not, any plans, XMOS, to make this possible?
Thanks,
Bill
dsp_vector library inconsistency
Would you mind letting us know which functions in particular you are calling and I'll try to explain the intent of the functions. Thanks
Thanks, Andrew, for the response.
I am looking at the lib_dsp.pdf version 3.0.0.
An example of the functions I would like to call is application of dsp_vector_mulv_complex() to the output of several dsp_fft_split_spectrum() calls. The latter works with variable type dsp_complex_t, whilst the former works with int32_t variable types. I copied below the prototypes from lib_dsp.pdf.
Please note that I understand at least one, albeit inefficient, way to make these and other lib_dsp functions work together (e.g., copying the dsp_complex_t real and imaginary parts to separate int32_t variables). I also know how to code up the complex multiply without using the library function (and thus avoiding the copying).
What I am asking is if there are any plans to re-write these, or add new, functions to be called with the same variable types, or if there is some "trick" I am missing that avoids inefficiencies like the copying I refer to. (I am assuming that a re-write or add, or "trick", would be more efficient than my xc-level code for the complex multiply.)
Note, also, it would be nice to have a library version of a dot product for complex vectors.
thanks,
Bill
dsp_fft_split_spectrum(dsp_complex_t pts[], const uint32_t N)
dsp_vector_mulv_complex(const int32_t input_vector_X_re[],
const int32_t input_vector_X_im[],
const int32_t input_vector_Y_re[],
const int32_t input_vector_Y_im[],
int32_t result_vector_R_re[],
int32_t result_vector_R_im[],
const int32_t vector_length,
const int32_t q_format)
I am looking at the lib_dsp.pdf version 3.0.0.
An example of the functions I would like to call is application of dsp_vector_mulv_complex() to the output of several dsp_fft_split_spectrum() calls. The latter works with variable type dsp_complex_t, whilst the former works with int32_t variable types. I copied below the prototypes from lib_dsp.pdf.
Please note that I understand at least one, albeit inefficient, way to make these and other lib_dsp functions work together (e.g., copying the dsp_complex_t real and imaginary parts to separate int32_t variables). I also know how to code up the complex multiply without using the library function (and thus avoiding the copying).
What I am asking is if there are any plans to re-write these, or add new, functions to be called with the same variable types, or if there is some "trick" I am missing that avoids inefficiencies like the copying I refer to. (I am assuming that a re-write or add, or "trick", would be more efficient than my xc-level code for the complex multiply.)
Note, also, it would be nice to have a library version of a dot product for complex vectors.
thanks,
Bill
dsp_fft_split_spectrum(dsp_complex_t pts[], const uint32_t N)
dsp_vector_mulv_complex(const int32_t input_vector_X_re[],
const int32_t input_vector_X_im[],
const int32_t input_vector_Y_re[],
const int32_t input_vector_Y_im[],
int32_t result_vector_R_re[],
int32_t result_vector_R_im[],
const int32_t vector_length,
const int32_t q_format)
Normally, when working in the frequency domain I work with complex multiplications meaning I will use: dsp_complex_mul_vector() or others from dsp_complex.h.
In your case if you would like to use dsp_vector_mulv_complex() then I would recommend writing a type for deinterleave and interleave function. An array of dsp_complex_t is such that each real value is at every other word aligned position, as are the imaginary values.
You could use a reinterpret cast to make this easy, i.e.
I hope that helps.
In your case if you would like to use dsp_vector_mulv_complex() then I would recommend writing a type for deinterleave and interleave function. An array of dsp_complex_t is such that each real value is at every other word aligned position, as are the imaginary values.
You could use a reinterpret cast to make this easy, i.e.
Code: Select all
int32_t re[L/2], im[L/2];
for(unsigned i=0; i<L; i+=2){
re[i/2] = (complex, int32_t[])[i];
im[i/2] = (complex, int32_t[])[i+1];
}
Converted Andrew's suggestion in to functions.
I've used vectorLength rather than the length of the interleaved array.
In general the overhead off de-interleaving after the FFT is better than doing vector processing of interleaved I and Q.
J
I've used vectorLength rather than the length of the interleaved array.
In general the overhead off de-interleaving after the FFT is better than doing vector processing of interleaved I and Q.
J
Code: Select all
void interleave (const int re[],
const int im[],
dsp_complex_t complex[],
const unsigned vectorLength)
{
for (unsigned i=0; i<vectorLength; i++) {
(complex, int32_t[])[2*i] = re[i];
(complex, int32_t[])[2*i+1] = im[i];
}
}
void deinterleave (const dsp_complex_t complex[],
int re[],
int im[],
const unsigned vectorLength)
{
for (unsigned i=0; i<vectorLength; i++) {
re[i] = (complex, int32_t[])[2*i];
im[i] = (complex, int32_t[])[2*i+1];
}
}
Andrew, you mentioned dsp_complex.h. Apologize if I'm a bit slow on the uptake, but is that part of the XMOS lib_dsp? I don't see dsp_complex when I download lib_dsp from XMOS.
cheers,
Bill
cheers,
Bill
Hello johned and Andrew,
Thanks for the code help, too. I am unfamiliar with that casting method.
Is "re = (complex, int32_t[])[2*i];" equivalent to "re = complex.re;" ?
If not, how do they differ?
Thanks,
Bill
Thanks for the code help, too. I am unfamiliar with that casting method.
Is "re = (complex, int32_t[])[2*i];" equivalent to "re = complex.re;" ?
If not, how do they differ?
Thanks,
Bill