JNIEXPORT jint JNICALL Java_utils_SVD_svd___3DII_3D_3D_3D (JNIEnv *env, jclass obj, jdoubleArray _A, jint _N, jint _M, jdoubleArray _S, jdoubleArray _Ut, jdoubleArray _Vt) { //double svd_end[2] = { -1e-10, 1e-10 }; SVDVerbosity = 0; double* At = env->GetDoubleArrayElements(_A, 0); DMat dAt = svdNewDMat(_N, _M); for (int i = 0; i < _N; ++i) for (int j = 0; j < _M; ++j) dAt->value[i][j] = At[i * _M + j]; SMat sAt = svdConvertDtoS(dAt); svdFreeDMat(dAt); env->ReleaseDoubleArrayElements(_A, At, 0); jsize maxRank = env->GetArrayLength(_S); //SVDRec Arec = svdLAS2(sAt, 0, SVD_MAX_ITER, svd_end, SVD_KAPPA); SVDRec Arec = svdLAS2A(sAt, maxRank); svdFreeSMat(sAt); if (Arec == NULL) { svdFreeSVDRec(Arec); printf("WARNING: SVDLIBC las2a returns NULL \n\n"); return 0; } int rank = Arec->d; double* S = env->GetDoubleArrayElements(_S, 0); double* Ut = env->GetDoubleArrayElements(_Ut, 0); double* Vt = env->GetDoubleArrayElements(_Vt, 0); for (int i = 0; i < rank; ++i) S[i] = Arec->S[i]; for (int i = 0; i < rank; ++i) for (int j = 0; j < _N; ++j) { int p = i * _N + j; Ut[p] = Arec->Ut->value[i][j]; } for (int i = 0; i < rank; ++i) for (int j = 0; j < _M; ++j) { int p = i * _M + j; Vt[p] += Arec->Vt->value[i][j]; } env->ReleaseDoubleArrayElements(_S, S, 0); env->ReleaseDoubleArrayElements(_Ut, Ut, 0); env->ReleaseDoubleArrayElements(_Vt, Vt, 0); svdFreeSVDRec(Arec); return rank; }
/* Transposes a dense matrix. */ DMat svdTransposeD(DMat D) { int r, c; DMat N = svdNewDMat(D->cols, D->rows); for (r = 0; r < D->rows; r++) for (c = 0; c < D->cols; c++) N->value[c][r] = D->value[r][c]; return N; }
/* Converts a sparse matrix to a dense one (without affecting the former) */ DMat svdConvertStoD(SMat S) { int i, c; DMat D = svdNewDMat(S->rows, S->cols); if (!D) { svd_error("svdConvertStoD: failed to allocate D"); return NULL; } for (i = 0, c = 0; i < S->vals; i++) { while (S->pointr[c + 1] <= i) c++; D->value[S->rowind[i]][c] = S->value[i]; } return D; }
static DMat svdLoadDenseTextFile(FILE *file) { long rows, cols, i, j; DMat D; if (fscanf(file, " %ld %ld", &rows, &cols) != 2) { svd_error("svdLoadDenseTextFile: bad file format"); return NULL; } D = svdNewDMat(rows, cols); if (!D) return NULL; for (i = 0; i < rows; i++) for (j = 0; j < cols; j++) { if (fscanf(file, " %lf", &(D->value[i][j])) != 1) { svd_error("svdLoadDenseTextFile: bad file format"); return NULL; } } return D; }
static DMat svdLoadDenseBinaryFile(FILE *file) { int rows, cols, i, j, e = 0; float f; DMat D; e += svd_readBinInt(file, &rows); e += svd_readBinInt(file, &cols); if (e) { svd_error("svdLoadDenseBinaryFile: bad file format"); return NULL; } D = svdNewDMat(rows, cols); if (!D) return NULL; for (i = 0; i < rows; i++) for (j = 0; j < cols; j++) { if (svd_readBinFloat(file, &f)) { svd_error("svdLoadDenseBinaryFile: bad file format"); return NULL; } D->value[i][j] = f; } return D; }
JNIEXPORT jint JNICALL Java_utils_SVD_lowRankSvd (JNIEnv *env, jclass obj, jdoubleArray _At, jdoubleArray _Bt, jint _N, jint _M, jint _R, jdoubleArray _S, jdoubleArray _Ut, jdoubleArray _Vt) { //double svd_end[2] = { -1e-10, 1e-10 }; SVDVerbosity = 0; double* At = env->GetDoubleArrayElements(_At, 0); double* Bt = env->GetDoubleArrayElements(_Bt, 0); DMat dAt = svdNewDMat(_R, _N); for (int i = 0; i < _R; ++i) for (int j = 0; j < _N; ++j) dAt->value[i][j] = At[i * _N + j]; SMat sAt = svdConvertDtoS(dAt); svdFreeDMat(dAt); DMat dBt = svdNewDMat(_R, _M); for (int i = 0; i < _R; ++i) for (int j = 0; j < _M; ++j) dBt->value[i][j] = Bt[i * _M + j]; SMat sBt = svdConvertDtoS(dBt); svdFreeDMat(dBt); env->ReleaseDoubleArrayElements(_At, At, 0); env->ReleaseDoubleArrayElements(_Bt, Bt, 0); //SVDRec Arec = svdLAS2(sAt, 0, SVD_MAX_ITER, svd_end, SVD_KAPPA); //SVDRec Brec = svdLAS2(sBt, 0, SVD_MAX_ITER, svd_end, SVD_KAPPA); SVDRec Arec = svdLAS2A(sAt, 0); SVDRec Brec = svdLAS2A(sBt, 0); svdFreeSMat(sAt); svdFreeSMat(sBt); if (Arec == NULL || Brec == NULL) { svdFreeSVDRec(Arec); svdFreeSVDRec(Brec); printf("WARNING: SVDLIBC las2a returns NULL \n\n"); return 0; } int ranka = Arec->d, rankb = Brec->d; if (ranka == 0 || rankb == 0) { printf("WARNING: one matrix has 0 rank. %d %d\n\n", ranka, rankb); return 0; } DMat dM = svdNewDMat(ranka, rankb); for (int i = 0; i < ranka; ++i) for (int j = 0; j < rankb; ++j) { double va = 0; for (int k = 0; k < _R; ++k) va += Arec->Ut->value[i][k] * Brec->Ut->value[j][k]; dM->value[i][j] = va * Arec->S[i] * Brec->S[j]; } SMat sM = svdConvertDtoS(dM); svdFreeDMat(dM); //SVDRec Mrec = svdLAS2(sM, 0, SVD_MAX_ITER, svd_end, SVD_KAPPA); SVDRec Mrec = svdLAS2A(sM, 0); svdFreeSMat(sM); int rank = 0; if (Mrec != NULL && Mrec->d > 0) { double* S = env->GetDoubleArrayElements(_S, 0); double* Ut = env->GetDoubleArrayElements(_Ut, 0); double* Vt = env->GetDoubleArrayElements(_Vt, 0); rank = Mrec->d; for (int i = 0; i < rank; ++i) S[i] = Mrec->S[i]; for (int i = 0; i < rank; ++i) for (int j = 0; j < _N; ++j) { int p = i * _N + j; for (int k = 0; k < ranka; ++k) Ut[p] += Mrec->Ut->value[i][k] * Arec->Vt->value[k][j]; } for (int i = 0; i < rank; ++i) for (int j = 0; j < _M; ++j) { int p = i * _M + j; for (int k = 0; k < rankb; ++k) Vt[p] += Mrec->Vt->value[i][k] * Brec->Vt->value[k][j]; } env->ReleaseDoubleArrayElements(_S, S, 0); env->ReleaseDoubleArrayElements(_Ut, Ut, 0); env->ReleaseDoubleArrayElements(_Vt, Vt, 0); } else { printf("WARNING: matrix M has 0 rank or las2a returns NULL \n\n"); } svdFreeSVDRec(Arec); svdFreeSVDRec(Brec); svdFreeSVDRec(Mrec); return rank; }