Loading...
Searching...
No Matches
volk_32fc_x2_divide_32fc

Overview

Divide first vector of complexes element-wise by second.

Dispatcher Prototype

void volk_32fc_x2_divide_32fc(lv_32fc_t* cVector, const lv_32fc_t* numeratorVector,
const lv_32fc_t* denumeratorVector, unsigned int num_points);

Inputs

- numeratorVector: The numerator complex values.
- numeratorVector: The denumerator complex values.
- num_points: The number of data points.

Outputs

- outputVector: The output vector complex floats.

Example divide a complex vector by itself, demonstrating the result should be pretty close to 1+0j.

int N = 10;
unsigned int alignment = volk_get_alignment();
lv_32fc_t* input_vector = (lv_32fc_t*)volk_malloc(sizeof(lv_32fc_t)*N, alignment);
lv_32fc_t* out = (lv_32fc_t*)volk_malloc(sizeof(lv_32fc_t)*N, alignment);
float delta = 2.f*M_PI / (float)N;
for(unsigned int ii = 0; ii < N; ++ii){
float real_1 = std::cos(0.3f * (float)ii);
float imag_1 = std::sin(0.3f * (float)ii);
input_vector[ii] = lv_cmake(real_1, imag_1);
}
volk_32fc_x2_divide_32fc(out, input_vector, input_vector, N);
for(unsigned int ii = 0; ii < N; ++ii){
printf("%1.4f%+1.4fj,", lv_creal(out[ii]), lv_cimag(out[ii]));
}
printf("\n");
volk_free(input_vector);
volk_free(out);

Numerical accuracy

The division of complex numbers (a + bj)/(c + dj) is calculated as (a*c + b*d)/(c*c + d*d) + (b*c - a*d)/(c*c + d*d) j.

Since Volk is built using unsafe math optimizations (-fcx-limited-range -funsafe-math-optimizations with gcc), after computing the two numerators and the denominator in the above formula, the compiler can either:

a) compute the two divisions; b) compute the inverse of the denominator, 1.0/(c*c + d*d), and then multiply this number by each of the numerators.

Under gcc, b) is allowed by -freciprocal-math, which is included in -funsafe-math-optimizations.

Depending on the architecture and the estimated cost of multiply and divide instructions, the compiler can perform a) or b). gcc performs a) under x86_64 and armv7, and b) under aarch64.

To avoid obtaining inf or nan in some architectures, care should be taken that c*c + d*d is not too small. In particular, if c*c + d*d < FLT_MAX, then the calculation of 1.0/(c*c + d*d) will yield inf.

For more information about numerical accuracy of complex division, see the following:

- https://godbolt.org/z/z9z5b9oM5 Compiler Explorer example showing how complex division is done in different architectures and with different optimization options.
- https://github.com/gcc-mirror/gcc/blob/7e3c58bfc1d957e48faf0752758da0fed811ed58/libgcc/libgcc2.c#L2707 gcc's implementation of the __divsc3 function, which implements C99 complex division semantics and handles several potential numerical problems. This function is used whenever -fcx-limited-range is not enabled.