* All data is assumed aligned. */
| 13 | * All data is assumed aligned. |
| 14 | */ |
| 15 | NPY_NO_EXPORT void |
| 16 | CFLOAT_vdot(char *ip1, npy_intp is1, char *ip2, npy_intp is2, |
| 17 | char *op, npy_intp n, void *NPY_UNUSED(ignore)) |
| 18 | { |
| 19 | #if defined(HAVE_CBLAS) |
| 20 | CBLAS_INT is1b = blas_stride(is1, sizeof(npy_cfloat)); |
| 21 | CBLAS_INT is2b = blas_stride(is2, sizeof(npy_cfloat)); |
| 22 | |
| 23 | if (is1b && is2b) { |
| 24 | double sum[2] = {0., 0.}; /* double for stability */ |
| 25 | |
| 26 | while (n > 0) { |
| 27 | CBLAS_INT chunk = n < NPY_CBLAS_CHUNK ? n : NPY_CBLAS_CHUNK; |
| 28 | float tmp[2]; |
| 29 | |
| 30 | CBLAS_FUNC(cblas_cdotc_sub)((CBLAS_INT)n, ip1, is1b, ip2, is2b, tmp); |
| 31 | sum[0] += (double)tmp[0]; |
| 32 | sum[1] += (double)tmp[1]; |
| 33 | /* use char strides here */ |
| 34 | ip1 += chunk * is1; |
| 35 | ip2 += chunk * is2; |
| 36 | n -= chunk; |
| 37 | } |
| 38 | ((float *)op)[0] = (float)sum[0]; |
| 39 | ((float *)op)[1] = (float)sum[1]; |
| 40 | } |
| 41 | else |
| 42 | #endif |
| 43 | { |
| 44 | float sumr = (float)0.0; |
| 45 | float sumi = (float)0.0; |
| 46 | npy_intp i; |
| 47 | |
| 48 | for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) { |
| 49 | const float ip1r = ((float *)ip1)[0]; |
| 50 | const float ip1i = ((float *)ip1)[1]; |
| 51 | const float ip2r = ((float *)ip2)[0]; |
| 52 | const float ip2i = ((float *)ip2)[1]; |
| 53 | |
| 54 | sumr += ip1r * ip2r + ip1i * ip2i; |
| 55 | sumi += ip1r * ip2i - ip1i * ip2r; |
| 56 | } |
| 57 | ((float *)op)[0] = sumr; |
| 58 | ((float *)op)[1] = sumi; |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | |
| 63 | /* |
nothing calls this directly
no test coverage detected