-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlinalg.cpp
More file actions
78 lines (65 loc) · 3.08 KB
/
Copy pathlinalg.cpp
File metadata and controls
78 lines (65 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <linalg.hpp>
#include <build_tree.hpp>
#include "cblas.h"
#include "lapacke.h"
#include <algorithm>
#include <numeric>
#include <cstdio>
#include <cstdlib>
#include <array>
void mul_AS(const Matrix* RU, const Matrix* RV, Matrix* A) {
if (A->M > 0 && A->N > 0) {
std::vector<double> tmp(A->M * A->N);
cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, A->M, A->N, A->M, 1., RU->A, RU->LDA, A->A, A->LDA, 0., &tmp[0], A->M);
cblas_dgemm(CblasColMajor, CblasNoTrans, CblasTrans, A->M, A->N, A->N, 1., &tmp[0], A->M, RV->A, RV->LDA, 0., A->A, A->LDA);
}
}
void gen_matrix(const EvalDouble& Eval, int64_t m, int64_t n, const double* bi, const double* bj, double Aij[], int64_t lda) {
const std::array<double, 3>* bi3 = reinterpret_cast<const std::array<double, 3>*>(bi);
const std::array<double, 3>* bi3_end = reinterpret_cast<const std::array<double, 3>*>(&bi[3 * m]);
const std::array<double, 3>* bj3 = reinterpret_cast<const std::array<double, 3>*>(bj);
const std::array<double, 3>* bj3_end = reinterpret_cast<const std::array<double, 3>*>(&bj[3 * n]);
std::for_each(bj3, bj3_end, [&](const std::array<double, 3>& j) -> void {
int64_t ix = std::distance(bj3, &j);
std::for_each(bi3, bi3_end, [&](const std::array<double, 3>& i) -> void {
int64_t iy = std::distance(bi3, &i);
double x = i[0] - j[0];
double y = i[1] - j[1];
double z = i[2] - j[2];
double d = std::sqrt(x * x + y * y + z * z);
Aij[iy + ix * lda] = Eval(d);
});
});
}
void compute_basis(const EvalDouble& eval, int64_t rank_max, int64_t M, double* A, int64_t LDA, double Xbodies[], int64_t N, const double bodies[]) {
if (M > 0 && N > 0) {
int64_t ldm = std::max(M, N);
std::vector<double> Aall(M * ldm, 0.), U(M * M), S(M * 2);
std::vector<int32_t> ipiv(M, 0);
gen_matrix(eval, N, M, bodies, Xbodies, &Aall[0], ldm);
LAPACKE_dgeqp3(LAPACK_COL_MAJOR, N, M, &Aall[0], ldm, &ipiv[0], &S[0]);
LAPACKE_dlaset(LAPACK_COL_MAJOR, 'L', M - 1, M - 1, 0., 0., &Aall[1], ldm);
LAPACKE_dgesvd(LAPACK_COL_MAJOR, 'N', 'A', M, M, &Aall[0], ldm, &S[0], NULL, M, &U[0], M, &S[M]);
int64_t rank = rank_max <= 0 ? M : std::min(rank_max, M);
if (rank > 0) {
if (rank < M)
LAPACKE_dgesv(LAPACK_COL_MAJOR, rank, M - rank, &U[0], M, (int32_t*)&S[0], &U[rank * M], M);
LAPACKE_dlaset(LAPACK_COL_MAJOR, 'F', rank, rank, 0., 1., &U[0], M);
}
std::vector<double> Xpiv(M * 3);
for (int64_t i = 0; i < M; i++) {
int64_t piv = (int64_t)ipiv[i] - 1;
if (rank > 0)
std::copy(&U[i * M], &U[i * M + rank], &Aall[piv * M]);
std::copy(&Xbodies[piv * 3], &Xbodies[piv * 3 + 3], &Xpiv[i * 3]);
}
std::copy(Xpiv.begin(), Xpiv.end(), Xbodies);
if (rank > 0) {
cblas_dgemm(CblasColMajor, CblasNoTrans, CblasTrans, M, rank, M, 1., A, LDA, &Aall[0], M, 0., &U[0], M);
LAPACKE_dgesvd(LAPACK_COL_MAJOR, 'A', 'O', M, rank, &U[0], M, &S[0], A, LDA, &U[0], M, &S[M]);
for (int64_t i = 0; i < rank; i++)
for (int64_t j = 0; j < rank; j++)
A[(M + i) * LDA + j] = S[j] * U[i * M + j];
}
}
}