| | 160 | * Solve the system A X = B or X A = B, using the LQUP decomposition of A |
| | 161 | * already computed inplace with LUdivine(FflasNoTrans, FflasNonUnit). |
| | 162 | * Version for A square. |
| | 163 | * If A is rank deficient, a solution is returned if the system is consistent, |
| | 164 | * Otherwise an info is 1 |
| | 165 | * |
| | 166 | * @param Side Determine wheter the resolution is left or right looking. |
| | 167 | * @param M row dimension of B |
| | 168 | * @param N col dimension of B |
| | 169 | * @param R rank of A |
| | 170 | * @param A input matrix |
| | 171 | * @param lda leading dimension of A |
| | 172 | * @param P column permutation of the LQUP decomposition of A |
| | 173 | * @param Q column permutation of the LQUP decomposition of A |
| | 174 | * @param B Right/Left hand side matrix. Initially stores B, finally stores the solution X. |
| | 175 | * @param ldb leading dimension of B |
| | 176 | * @info Succes of the computation: 0 if successfull, >0 if system is inconsistent |
| | 177 | */ |
| | 178 | template <class Field> |
| | 179 | static typename Field::Element * |
| | 180 | fgetrs (const Field& F, |
| | 181 | const FFLAS_SIDE Side, |
| | 182 | const size_t M, const size_t N, const size_t R, |
| | 183 | const Field::Element *A, const size_t lda, |
| | 184 | const size_t *P, const size_t *Q, |
| | 185 | Field::Element *B, const size_t ldb, |
| | 186 | int * info){ |
| | 187 | |
| | 188 | static zero; |
| | 189 | F.init (zero, 0.0); |
| | 190 | if (Side == FflasLeft) { // Left looking solve A X = B |
| | 191 | |
| | 192 | SolveLB (F, FflasLeft, M, N, R, A, lda, Q, B, ldb); |
| | 193 | |
| | 194 | applyP (F, FflasLeft, FflasNoTrans, N, 0, R, B, ldb, Q); |
| | 195 | |
| | 196 | bool consistent = true; |
| | 197 | for (size_t i = R; i < M; ++i) |
| | 198 | for (size_t j = 0; j < N; ++j) |
| | 199 | if (!F.isZero (*(B + i*ldb + j))) |
| | 200 | consistent = false; |
| | 201 | if (!consistent) { |
| | 202 | std::cerr<<"System is inconsistent"<<std::endl; |
| | 203 | *info = 1; |
| | 204 | } |
| | 205 | // The last rows of B are now supposed to be 0 |
| | 206 | // for (size_t i = R; i < M; ++i) |
| | 207 | // for (size_t j = 0; j < N; ++j) |
| | 208 | // *(B + i*ldb + j) = zero; |
| | 209 | |
| | 210 | ftrsm (F, FflasLeft, FflasUpper, FflasNoTrans, FflasNonUnit, |
| | 211 | R, N, one, A, lda , B, ldb); |
| | 212 | |
| | 213 | applyP (F, FflasLeft, FflasTrans, N, 0, R, B, ldb, P); |
| | 214 | |
| | 215 | return B; |
| | 216 | |
| | 217 | } else { // Right Looking X A = B |
| | 218 | |
| | 219 | applyP (F, FflasRight, FflasTrans, M, 0, R, B, ldb, P); |
| | 220 | |
| | 221 | ftrsm (F, FflasRight, FflasUpper, FflasNoTrans, FflasNonUnit, |
| | 222 | N, R, one, A, lda , B, ldb); |
| | 223 | |
| | 224 | fgemm (F, FflasNoTrans, FflasNoTrans, M, N-R, R, one, |
| | 225 | B, ldb, A+R, lda, mone, B+R, ldb); |
| | 226 | |
| | 227 | bool consistent = true; |
| | 228 | for (size_t i = 0; i < M; ++i) |
| | 229 | for (size_t j = R; j < N; ++j) |
| | 230 | if (!F.isZero (*(B + i*ldb + j))) |
| | 231 | consistent = false; |
| | 232 | if (!consistent) { |
| | 233 | std::cerr<<"System is inconsistent"<<std::endl; |
| | 234 | *info = 1; |
| | 235 | } |
| | 236 | // The last cols of B are now supposed to be 0 |
| | 237 | |
| | 238 | applyP (F, FflasRight, FflasNoTrans, M, 0, R, B, ldb, Q); |
| | 239 | |
| | 240 | SolveLB (F, FflasRight, M, N, R, A, lda, Q, B, ldb); |
| | 241 | } |
| | 242 | } |
| | 243 | |
| | 244 | /** |
| | 245 | * Solve the system A X = B or X A = B, using the LQUP decomposition of A |
| | 246 | * already computed inplace with LUdivine(FflasNoTrans, FflasNonUnit). |
| | 247 | * Version for A rectangular. |
| | 248 | * If A is rank deficient, a solution is returned if the system is consistent, |
| | 249 | * Otherwise an info is 1 |
| | 250 | * |
| | 251 | * @param Side Determine wheter the resolution is left or right looking. |
| | 252 | * @param M row dimension of A |
| | 253 | * @param N col dimension of A |
| | 254 | * @param NRHS number of columns (if Side = FflasLeft) or row (if Side = FflasRight) of the matrices X and B |
| | 255 | * @param R rank of A |
| | 256 | * @param A input matrix |
| | 257 | * @param lda leading dimension of A |
| | 258 | * @param P column permutation of the LQUP decomposition of A |
| | 259 | * @param Q column permutation of the LQUP decomposition of A |
| | 260 | * @param X solution matrix |
| | 261 | * @param ldx leading dimension of X |
| | 262 | * @param B Right/Left hand side matrix. |
| | 263 | * @param ldb leading dimension of B |
| | 264 | * @info Succes of the computation: 0 if successfull, >0 if system is inconsistent |
| | 265 | */ |
| | 266 | template <class Field> |
| | 267 | static typename Field::Element * |
| | 268 | fgetrs (const Field& F, |
| | 269 | const FFLAS_SIDE Side, |
| | 270 | const size_t M, const size_t N, const size_t NRHS, const size_t R, |
| | 271 | const Field::Element *A, const size_t lda, |
| | 272 | const size_t *P, const size_t *Q, |
| | 273 | Field::Element *X, const size_t ldb, |
| | 274 | const Field::Element *B, const size_t ldb, |
| | 275 | int * info) { |
| | 276 | |
| | 277 | static zero; |
| | 278 | F.init (zero, 0.0); |
| | 279 | if (Side == FflasLeft) { // Left looking solve A X = B |
| | 280 | |
| | 281 | for (size_t i=0; i < N; ++i) |
| | 282 | fcopy (F, NRHS, X + i*ldx, 1, B + i*ldb, 1); |
| | 283 | |
| | 284 | SolveLB (F, FflasLeft, M, N, R, A, lda, Q, B, ldb); |
| | 285 | |
| | 286 | applyP (F, FflasLeft, FflasNoTrans, N, 0, R, B, ldb, Q); |
| | 287 | |
| | 288 | bool consistent = true; |
| | 289 | for (size_t i = R; i < M; ++i) |
| | 290 | for (size_t j = 0; j < N; ++j) |
| | 291 | if (!F.isZero (*(B + i*ldb + j))) |
| | 292 | consistent = false; |
| | 293 | if (!consistent) { |
| | 294 | std::cerr<<"System is inconsistent"<<std::endl; |
| | 295 | *info = 1; |
| | 296 | } |
| | 297 | // The last rows of B are now supposed to be 0 |
| | 298 | // for (size_t i = R; i < M; ++i) |
| | 299 | // for (size_t j = 0; j < N; ++j) |
| | 300 | // *(B + i*ldb + j) = zero; |
| | 301 | |
| | 302 | ftrsm (F, FflasLeft, FflasUpper, FflasNoTrans, FflasNonUnit, |
| | 303 | R, N, one, A, lda , B, ldb); |
| | 304 | |
| | 305 | applyP (F, FflasLeft, FflasTrans, N, 0, R, B, ldb, P); |
| | 306 | |
| | 307 | return B; |
| | 308 | |
| | 309 | } else { // Right Looking X A = B |
| | 310 | |
| | 311 | for (size_t i=0; i < NRHS; ++i) |
| | 312 | fcopy (F, M, X + i*ldx, 1, B + i*ldb, 1); |
| | 313 | |
| | 314 | applyP (F, FflasRight, FflasTrans, M, 0, R, B, ldb, P); |
| | 315 | |
| | 316 | ftrsm (F, FflasRight, FflasUpper, FflasNoTrans, FflasNonUnit, |
| | 317 | N, R, one, A, lda , B, ldb); |
| | 318 | |
| | 319 | fgemm (F, FflasNoTrans, FflasNoTrans, M, N-R, R, one, |
| | 320 | B, ldb, A+R, lda, mone, B+R, ldb); |
| | 321 | |
| | 322 | bool consistent = true; |
| | 323 | for (size_t i = 0; i < M; ++i) |
| | 324 | for (size_t j = R; j < N; ++j) |
| | 325 | if (!F.isZero (*(B + i*ldb + j))) |
| | 326 | consistent = false; |
| | 327 | if (!consistent) { |
| | 328 | std::cerr<<"System is inconsistent"<<std::endl; |
| | 329 | *info = 1; |
| | 330 | } |
| | 331 | // The last cols of B are now supposed to be 0 |
| | 332 | |
| | 333 | applyP (F, FflasRight, FflasNoTrans, M, 0, R, B, ldb, Q); |
| | 334 | |
| | 335 | SolveLB (F, FflasRight, M, N, R, A, lda, Q, B, ldb); |
| | 336 | } |
| | 337 | } |
| | 338 | |
| | 339 | /** |
| | 340 | * @brief Square system solver |
| | 341 | * @param Field The computation domain |
| | 342 | * @param Side Determine wheter the resolution is left or right looking |
| | 343 | * @param M row dimension of B |
| | 344 | * @param N col dimension of B |
| | 345 | * @param A input matrix |
| | 346 | * @param lda leading dimension of A |
| | 347 | * @param P column permutation of the LQUP decomposition of A |
| | 348 | * @param Q column permutation of the LQUP decomposition of A |
| | 349 | * @param B Right/Left hand side matrix. Initially contains B, finally contains the solution X. |
| | 350 | * @param ldb leading dimension of B |
| | 351 | * @info Succes of the computation: 0 if successfull, >0 if system is inconsistent |
| | 352 | * @return a pointer to B |
| | 353 | * |
| | 354 | * Solve the system A X = B or X A = B. |
| | 355 | * Version for A square. |
| | 356 | * If A is rank deficient, a solution is returned if the system is consistent, |
| | 357 | * Otherwise an info is 1 |
| | 358 | */ |
| | 359 | template <class Field> |
| | 360 | static typename Field::Element * |
| | 361 | fgesv (const FFLAS_SIDE Side, |
| | 362 | const size_t M, const size_t N, |
| | 363 | const Field::Element *A, const size_t lda, |
| | 364 | Field::Element *B, const size_t ldb, |
| | 365 | int * info){ |
| | 366 | |
| | 367 | size_t Na; |
| | 368 | if (Side == FflasLeft) |
| | 369 | Na = M; |
| | 370 | else |
| | 371 | Na = N; |
| | 372 | |
| | 373 | size_t P = new size_t[Na]; |
| | 374 | size_t Q = new size_t[Na]; |
| | 375 | |
| | 376 | size_t R = LUdivine (F, FflasNonUnit, FflasNoTrans, Na, Na, A, lda, P, Q, FfpackLQUP); |
| | 377 | |
| | 378 | fgetrs (F, Side, M, N , R, A, lda, P, Q, B, ldb, info); |
| | 379 | |
| | 380 | delete[] P; |
| | 381 | delete[] Q; |
| | 382 | |
| | 383 | return B; |
| | 384 | } |
| | 385 | |
| | 386 | /** |