This is generic C implementation of mv. It may work with unaligned data. ********************************************************************/
| 119 | It may work with unaligned data. |
| 120 | ********************************************************************/ |
| 121 | void ialglib::mv_generic(int m, int n, const double *a, const double *x, double *y, int stride, double alpha, double beta) |
| 122 | { |
| 123 | if( m==32 && n==32 ) |
| 124 | { |
| 125 | // |
| 126 | // 32x32, may be we have something better than general implementation |
| 127 | // |
| 128 | mv_32(a, x, y, stride, alpha, beta); |
| 129 | } |
| 130 | else |
| 131 | { |
| 132 | int i, k, m2, n8, n2, ntrail2; |
| 133 | const double *pa0, *pa1, *pb; |
| 134 | |
| 135 | // |
| 136 | // First M/2 rows of A are processed in pairs. |
| 137 | // Highly optimized code is used. |
| 138 | // |
| 139 | m2 = m/2; |
| 140 | n8 = n/8; |
| 141 | ntrail2 = (n-8*n8)/2; |
| 142 | for(i=0; i<m2; i++) |
| 143 | { |
| 144 | double v0 = 0, v1 = 0; |
| 145 | |
| 146 | // |
| 147 | // 'a' points to the part of the matrix which |
| 148 | // is not processed yet |
| 149 | // |
| 150 | pb = x; |
| 151 | pa0 = a; |
| 152 | pa1 = a+alglib_r_block; |
| 153 | a += alglib_twice_r_block; |
| 154 | |
| 155 | // |
| 156 | // 8 elements per iteration |
| 157 | // |
| 158 | for(k=0; k<n8; k++) |
| 159 | { |
| 160 | v0 += pa0[0]*pb[0]; |
| 161 | v1 += pa1[0]*pb[0]; |
| 162 | v0 += pa0[1]*pb[1]; |
| 163 | v1 += pa1[1]*pb[1]; |
| 164 | v0 += pa0[2]*pb[2]; |
| 165 | v1 += pa1[2]*pb[2]; |
| 166 | v0 += pa0[3]*pb[3]; |
| 167 | v1 += pa1[3]*pb[3]; |
| 168 | v0 += pa0[4]*pb[4]; |
| 169 | v1 += pa1[4]*pb[4]; |
| 170 | v0 += pa0[5]*pb[5]; |
| 171 | v1 += pa1[5]*pb[5]; |
| 172 | v0 += pa0[6]*pb[6]; |
| 173 | v1 += pa1[6]*pb[6]; |
| 174 | v0 += pa0[7]*pb[7]; |
| 175 | v1 += pa1[7]*pb[7]; |
| 176 | pa0 += 8; |
| 177 | pa1 += 8; |
| 178 | pb += 8; |
nothing calls this directly
no outgoing calls
no test coverage detected