This subroutine calculates fast 32x32 real matrix-vector product: y := beta*y + alpha*A*x using either generic C code or native optimizations (if available) IMPORTANT: * A must be stored in row-major order, stride is alglib_r_block, aligned on alglib_simd_alignment boundary * X must be aligned on alglib_simd_alignment boundary * Y may be non-aligned *************************************
| 42 | * Y may be non-aligned |
| 43 | ********************************************************************/ |
| 44 | void ialglib::mv_32(const double *a, const double *x, double *y, int stride, double alpha, double beta) |
| 45 | { |
| 46 | int i, k; |
| 47 | const double *pa0, *pa1, *pb; |
| 48 | |
| 49 | pa0 = a; |
| 50 | pa1 = a+alglib_r_block; |
| 51 | pb = x; |
| 52 | for(i=0; i<16; i++) |
| 53 | { |
| 54 | double v0 = 0, v1 = 0; |
| 55 | for(k=0; k<4; k++) |
| 56 | { |
| 57 | v0 += pa0[0]*pb[0]; |
| 58 | v1 += pa1[0]*pb[0]; |
| 59 | v0 += pa0[1]*pb[1]; |
| 60 | v1 += pa1[1]*pb[1]; |
| 61 | v0 += pa0[2]*pb[2]; |
| 62 | v1 += pa1[2]*pb[2]; |
| 63 | v0 += pa0[3]*pb[3]; |
| 64 | v1 += pa1[3]*pb[3]; |
| 65 | v0 += pa0[4]*pb[4]; |
| 66 | v1 += pa1[4]*pb[4]; |
| 67 | v0 += pa0[5]*pb[5]; |
| 68 | v1 += pa1[5]*pb[5]; |
| 69 | v0 += pa0[6]*pb[6]; |
| 70 | v1 += pa1[6]*pb[6]; |
| 71 | v0 += pa0[7]*pb[7]; |
| 72 | v1 += pa1[7]*pb[7]; |
| 73 | pa0 += 8; |
| 74 | pa1 += 8; |
| 75 | pb += 8; |
| 76 | } |
| 77 | y[0] = beta*y[0]+alpha*v0; |
| 78 | y[stride] = beta*y[stride]+alpha*v1; |
| 79 | |
| 80 | // |
| 81 | // now we've processed rows I and I+1, |
| 82 | // pa0 and pa1 are pointing to rows I+1 and I+2. |
| 83 | // move to I+2 and I+3. |
| 84 | // |
| 85 | pa0 += alglib_r_block; |
| 86 | pa1 += alglib_r_block; |
| 87 | pb = x; |
| 88 | y+=2*stride; |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | |
| 93 | /******************************************************************** |
nothing calls this directly
no outgoing calls
no test coverage detected