void MatrixTest::testMatrixMatrixOperations () { Matrix<2,3,int> lMatrix; Matrix<3,2,int> rMatrix; Matrix<2,2,int> result(0); assignList(lMatrix) = 1, 2, 3, 4, 5, 6; assignList(rMatrix) = 6, 5, 4, 3, 2, 1; // Matrix matrix multiplication multiply (lMatrix, rMatrix, result); validateEquals (result(0,0), 20); validateEquals (result(0,1), 14); validateEquals (result(1,0), 56); validateEquals (result(1,1), 41); // Bitwise comparison Matrix<2,3,int> matrixA(1); Matrix<2,3,int> matrixB(2); validate (matrixA == matrixA); validate (! (matrixA == matrixB)); // Test equalsReturnIndex Matrix<2,3,double> matrix1(1); Matrix<2,3,double> matrix2(2); int i=equalsReturnIndex(matrix1,matrix2); validateEquals(i,0); }
TEST(Matrix, MatrixMultiplication) { core::F32_t valuesA[4][4]; core::F32_t valuesB[4][4]; core::F32_t valueA = 0; core::F32_t valueB = 15; for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { valuesA[i][j] = valueA; valuesB[i][j] = valueB; valueA++; valueB--; } } core::Matrix4x4 matrixA(valuesA); core::Matrix4x4 matrixB(valuesB); core::Matrix4x4 result; core::Matrix4x4::multiply(matrixA, matrixB, result); ASSERT_EQ(result.m[0][0], 34); ASSERT_EQ(result.m[0][1], 28); ASSERT_EQ(result.m[0][2], 22); ASSERT_EQ(result.m[0][3], 16); ASSERT_EQ(result.m[1][0], 178); ASSERT_EQ(result.m[1][1], 156); ASSERT_EQ(result.m[1][2], 134); ASSERT_EQ(result.m[1][3], 112); ASSERT_EQ(result.m[2][0], 322); ASSERT_EQ(result.m[2][1], 284); ASSERT_EQ(result.m[2][2], 246); ASSERT_EQ(result.m[2][3], 208); ASSERT_EQ(result.m[3][0], 466); ASSERT_EQ(result.m[3][1], 412); ASSERT_EQ(result.m[3][2], 358); ASSERT_EQ(result.m[3][3], 304); }
// estimate the feature transform for the given data (typically speaker adaptation data) Transform *FMLLREstimator::estimateTransform(Transform *transformInitial) { Matrix<double> matrixW(m_iDim,m_iDim+1); Matrix<float> matrixWF(m_iDim,m_iDim+1); Matrix<double> matrixA(m_iDim,m_iDim); Vector<double> vAux(m_iDim+1); // starting from scratch: bias = 0.0 and A = identity if (transformInitial == NULL) { matrixA.setIdentity(); } // starting from another transform else { assert(0); } // compute the matrix of cofactors of A Matrix<double> matrixP(matrixA); matrixP.matrixCofactor(); // initialize the transform // iterative update for(int iIteration = 0 ; iIteration < m_iIterations ; ++iIteration) { // compute the transform row by row for(int i=0 ; i < m_iDim ; ++i) { // invert G(i) (this is suboptimal, the inversion needs to be // done just once then it can be reused across iterations) Matrix<double> matrixGInverted(*m_matrixG[i]); matrixGInverted.invert(); // compute alpha (it implies solving a quadratic equation and selecting the solution // that produces a higher increase of the objective function) // get the zero extended vector of cofactors for the ith row Vector<double> vCofactor(matrixP.getRow(i)); vCofactor.appendFront(0.0); // compute constants double dBeta = m_fOccupancyTotal; Vector<double> vAux(m_iDim+1); vAux.mul(vCofactor,matrixGInverted); double dA = vAux.mul(vCofactor); double dB = vAux.mul(m_matrixK->getRow(i)); double dC = -1.0*dBeta; // there are two possible solutions double dAlpha1 = (-1.0*dB + sqrt(dB*dB - 4.0*dA*dC))/(2.0*dA); double dAlpha2 = (-1.0*dB - sqrt(dB*dB - 4.0*dA*dC))/(2.0*dA); // we let the objective function decide which solution is better (higher likelihood increase) double dAuxiliarFunction1 = dBeta*log(fabs(dAlpha1*dA+dB)) - 0.5*dAlpha1*dAlpha1*dA; double dAuxiliarFunction2 = dBeta*log(fabs(dAlpha2*dA+dB)) - 0.5*dAlpha2*dAlpha2*dA; double dAlpha = (dAuxiliarFunction1 > dAuxiliarFunction2) ? dAlpha1 : dAlpha2; // compute the w(i) Vector<double> vAux2(m_matrixK->getRow(i)); Vector<double> vCofactorRowEx(matrixP.getRow(i)); vCofactorRowEx.appendFront(0.0); vAux2.add(dAlpha,vCofactorRowEx); matrixW.getRow(i).mul(vAux2,matrixGInverted); // update A matrixA.getRow(i).copy(matrixW.getRowData(i)+1,m_iDim); // compute the matrix of cofactors after updating the row of the transform matrixP.copy(matrixA); matrixP.matrixCofactor(); } // compute the log(|A|) Matrix<double> matrixAInverted(matrixA); float fDet = (float)matrixAInverted.invert(); if (fDet == 0) { BVC_ERROR << "the A matrix is singular!, can't compute inverse"; } printf("log(|A|) = %8.4f\n",log(fDet)); } // create the transform Matrix<float> matrixWFloat(matrixW); return new Transform(TRANSFORM_TYPE_AFFINE,matrixWFloat); }