// // core.cpp // MNN // // Created by MNN on 2023/04/18. // Copyright © 2018][Alibaba Group Holding Limited // #include #include "cv/core.hpp" #include "cv/imgproc/geometric.hpp" #include #include namespace MNN { namespace CV { #ifndef FLT_EPSILON #define FLT_EPSILON 1.19209290E-07F #endif #define det2(m) ((double)m(0,0)*m(1,1) - (double)m(0,1)*m(1,0)) #define det3(m) (m(0,0)*((double)m(1,1)*m(2,2) - (double)m(1,2)*m(2,1)) - \ m(0,1)*((double)m(1,0)*m(2,2) - (double)m(1,2)*m(2,0)) + \ m(0,2)*((double)m(1,0)*m(2,1) - (double)m(1,1)*m(2,0))) int LUImpl(float* A, int astep, int m, float* b, int bstep, int n, float eps) { int i, j, k, p = 1; for (i = 0; i < m; i++) { k = i; for (j = i+1; j < m; j++) { if (fabs(A[j*astep + i]) > fabs(A[k*astep + i])) { k = j; } } if (fabs(A[k*astep + i]) < eps) { return 0; } if (k != i) { for (j = i; j < m; j++) { std::swap(A[i*astep + j], A[k*astep + j]); } if (b) { for (j = 0; j < n; j++) { std::swap(b[i*bstep + j], b[k*bstep + j]); } } p = -p; } float d = -1/A[i*astep + i]; for (j = i+1; j < m; j++) { float alpha = A[j*astep + i]*d; for (k = i+1; k < m; k++) { A[j*astep + k] += alpha*A[i*astep + k]; } if (b) { for (k = 0; k < n; k++) { b[j*bstep + k] += alpha*b[i*bstep + k]; } } } } if (b) { for (i = m-1; i >= 0; i--) { for (j = 0; j < n; j++) { float s = b[i*bstep + j]; for (k = i+1; k < m; k++) { s -= A[i*astep + k]*b[k*bstep + j]; } b[i*bstep + j] = s/A[i*astep + i]; } } } return p; } std::pair solve(VARP src1, VARP src2, int method) { method = DECOMP_LU; int row1, col1, channel1, row2, col2, channel2; getVARPSize(src1, &row1, &col1, &channel1); getVARPSize(src2, &row2, &col2, &channel2); auto dst = _Input({col1, col2}); bool is_normal = (method == DECOMP_NORMAL); bool result = true; // check case of a single equation and small matrix if ((method == DECOMP_LU || method == DECOMP_CHOLESKY) && row1 <= 3 && row1 == col1 && col2 == 1) { auto ptr1 = src1->readMap(); auto ptr2 = src2->readMap(); auto dstptr = dst->writeMap(); #define Sf(y, x) ptr1[y * col1 + x] #define bf(y) ptr2[y * col2] #define Df(y, x) dstptr[y * col2 + x] if (row1 == 2) { double d = det2(Sf); if (d != 0.) { double t; d = 1./d; t = (float)(((double)bf(0) * Sf(1,1) - (double)bf(1) * Sf(0,1)) * d); Df(1,0) = (float)(((double)bf(1) * Sf(0,0) - (double)bf(0) * Sf(1,0)) * d); Df(0,0) = (float)t; } else { result = false; } } else if (row1 == 3) { double d = det3(Sf); if (d != 0.) { float t[3]; d = 1./d; t[0] = (float)(d* (bf(0)*((double)Sf(1,1)*Sf(2,2) - (double)Sf(1,2)*Sf(2,1)) - Sf(0,1)*((double)bf(1)*Sf(2,2) - (double)Sf(1,2)*bf(2)) + Sf(0,2)*((double)bf(1)*Sf(2,1) - (double)Sf(1,1)*bf(2)))); t[1] = (float)(d* (Sf(0,0)*(double)(bf(1)*Sf(2,2) - (double)Sf(1,2)*bf(2)) - bf(0)*((double)Sf(1,0)*Sf(2,2) - (double)Sf(1,2)*Sf(2,0)) + Sf(0,2)*((double)Sf(1,0)*bf(2) - (double)bf(1)*Sf(2,0)))); t[2] = (float)(d* (Sf(0,0)*((double)Sf(1,1)*bf(2) - (double)bf(1)*Sf(2,1)) - Sf(0,1)*((double)Sf(1,0)*bf(2) - (double)bf(1)*Sf(2,0)) + bf(0)*((double)Sf(1,0)*Sf(2,1) - (double)Sf(1,1)*Sf(2,0)))); Df(0,0) = t[0]; Df(1,0) = t[1]; Df(2,0) = t[2]; } else { result = false; } } else { double d = Sf(0,0); if (d != 0.) { Df(0,0) = (float)(bf(0) / d); } else { result = false; } } return std::make_pair(result, dst); } // other matrix if (row1 < col1) { MNN_ERROR("The function can not solve under-determined linear systems."); return std::make_pair(false, dst); } VARP a; if (is_normal) { } else if (method != DECOMP_SVD) { a = _Clone(src1, true); } else { a = _Transpose(src1, {1, 0}); } if (!is_normal) { if( method == DECOMP_LU || method == DECOMP_CHOLESKY ) { dst = _Clone(src2); } } else { if (method == DECOMP_LU || method == DECOMP_CHOLESKY) { dst = _MatMul(src1, src2); } else { src2 = _MatMul(src1, src2); } } a.fix(Express::VARP::CONSTANT); dst.fix(Express::VARP::CONSTANT); if (method == DECOMP_LU) { result = LUImpl(a->writeMap(), row1, col1, dst->writeMap(), col2, col2, FLT_EPSILON * 10); } return std::make_pair(result, dst); } } // CV } // MNN