Max*_*ell 12 c++ fortran lapack 128-bit
我正在尝试使用Lapack进行矩阵奇异值分解(SVD)的128位精度计算,我发现有一些黑色编译器魔术可以实现这一点.英特尔Fortran编译器(ifort)支持-r16指示编译器将所有变量声明为DOUBLE PRECISION128位实数的选项.所以我使用以下方法编译了Lapack和BLAS:
ifort -O3 -r16 -c isamax.f -o isamax.o
ifort -O3 -r16 -c sasum.f -o sasum.o
...
Run Code Online (Sandbox Code Playgroud)
要将其合并到我的程序(也就是C++)中,我可以使用英特尔C++编译器(icc)和-Qoption,cpp,--extended_float_type创建数据类型_Quad为128位浮点变量的选项.我的SVD示例如下所示:
#include "stdio.h"
#include "iostream"
#include "vector"
using namespace std;
typedef _Quad scalar;
//FORTRAN BINDING
extern "C" void dgesvd_(char *JOBU, char *JOBVT, int *M, int *N,
scalar *A, int *LDA,
scalar *S,
scalar *U, int *LDU,
scalar *VT, int *LDVT,
scalar *WORK, int *LWORK, int *INFO);
int main() {
cout << "Size of scalar: " << sizeof(scalar) << endl;
int N=2;
vector< scalar > A(N*N);
vector< scalar > S(N);
vector< scalar > U(N*N);
vector< scalar > VT(N*N);
// dummy input matrix
A[0] = 1.q;
A[1] = 2.q;
A[2] = 2.q;
A[3] = 3.q;
cout << "Input matrix: " << endl;
for(int i = 0; i < N; i++) {
for(int j = 0;j < N; j++)
cout << double(A[i*N+j]) << "\t";
cout << endl;
}
cout << endl;
char JOBU='A';
char JOBVT='A';
int LWORK=-1;
scalar test;
int INFO;
// allocate memory
dgesvd_(&JOBU, &JOBVT, &N, &N,
&A[0], &N,
&S[0],
&U[0], &N,
&VT[0], &N,
&test, &LWORK, &INFO);
LWORK=test;
int size=int(test);
cout<<"Needed workspace size: "<<int(test)<<endl<<endl;
vector< scalar > WORK(size);
// run...
dgesvd_(&JOBU, &JOBVT, &N, &N,
&A[0], &N,
&S[0],
&U[0], &N,
&VT[0], &N,
&WORK[0], &LWORK, &INFO);
// output as doubles
cout << "Singular values: " << endl;
for(int i = 0;i < N; i++)
cout << double(S[i]) << endl;
cout << endl;
cout << "U: " << endl;
for(int i = 0;i < N; i++) {
for(int j = 0;j < N; j++)
cout << double(U[N*i+j]) << "\t";
cout << endl;
}
cout << "VT: " << endl;
for(int i = 0;i < N; i++) {
for(int j = 0;j < N; j++)
cout << double(VT[N*i+j]) << "\t";
cout << endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
用.编译
icc test.cpp -g -Qoption,cpp,--extended_float_type -lifcore ../lapack-3.4.0/liblapack.a ../BLAS/blas_LINUX.a
Run Code Online (Sandbox Code Playgroud)
到目前为止一切正常.但输出是:
Size of scalar: 16 Input matrix: 1 2 2 3 Needed workspace size: 134 Singular values: inf inf U: -0.525731 -0.850651 -0.850651 0.525731 VT: -0.525731 0.850651 -0.850651 -0.525731
我检查过U和VT是否正确,但奇异值显然不是.有没有人知道为什么会发生这种情况或者如何绕过它?
谢谢你的帮助.
小智 2
当使用具有扩展精度的外部库时,还要检查它们是否使用旧式d1mach.f、r1mach.f、i1mach.f来获取有关机器算术的信息。这里可能需要调整一些值。
这对于 Lapack 来说不是问题,它使用 dlamch.f(此处为http://www.netlib.org/lapack/util/dlamch.f),它使用 Fortran 90 内在函数来获取这些机器常量。
但如果您使用 BLAS 或 SLATEC,则可能会出现问题。