2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 * @file FBaseDoubleMatrix.cpp
20 * @brief This is the implementation for DoubleMatrix class.
23 #include <FBaseDoubleMatrix.h>
24 #include <FBaseSysLog.h>
25 #include <unique_ptr.h>
27 namespace Tizen { namespace Base
30 DoubleMatrix::DoubleMatrix(void)
38 DoubleMatrix::DoubleMatrix(const DoubleMatrix& rhs)
41 , __column(rhs.__column)
43 AllocateCapacity(__row, __column);
44 for (int i = 0; i < __row; i++)
46 for (int j = 0; j < __column; j++)
48 __pMatrix[i][j] = rhs.__pMatrix[i][j];
53 DoubleMatrix::DoubleMatrix(int rowCount, int columnCount)
56 , __column(columnCount)
58 AllocateCapacity(__row, __column);
62 DoubleMatrix::DoubleMatrix(int rowCount, int columnCount, const double* pArray, bool rowMajor)
65 , __column(columnCount)
67 AllocateCapacity(__row, __column);
72 for (int i = 0; i < __row; i++)
74 for (int j = 0; j < __column; j++)
76 __pMatrix[i][j] = pArray[i * __row + j];
82 for (int i = 0; i < __column; i++)
84 for (int j = 0; j < __row; j++)
86 __pMatrix[j][i] = pArray[i * __column + j];
97 DoubleMatrix::DoubleMatrix(int rowCount, int columnCount, const double* pArray[])
100 , __column(columnCount)
102 AllocateCapacity(__row, __column);
105 for (int i = 0; i < __row; i++)
107 for (int j = 0; j < __column; j++)
109 __pMatrix[i][j] = pArray[i][j];
119 DoubleMatrix::~DoubleMatrix(void)
121 for ( int i = 0 ; i < __row ; i++ )
123 delete[] __pMatrix[i];
130 DoubleMatrix::operator ==(const DoubleMatrix& rhs) const
137 if ((__row != rhs.__row) || (__column != rhs.__column))
142 for (int i = 0; i < __row; i++)
144 for (int j = 0; j < __column; j++)
146 if (__pMatrix[i][j] != rhs.__pMatrix[i][j])
157 DoubleMatrix::operator !=(const DoubleMatrix& rhs) const
159 return !(*this == rhs);
163 DoubleMatrix::operator =(const DoubleMatrix& rhs)
170 SysTryReturn(NID_BASE, (__row == rhs.__row) && (__column == rhs.__column), *this, E_INVALID_ARG,
171 "[%s] Invalid argument is used. Either row or column count of the current instance is not same with that of the specified instance.",
172 GetErrorMessage(E_INVALID_ARG));
174 for (int i = 0; i < __row; i++)
176 for (int j = 0; j < __column; j++)
178 __pMatrix[i][j] = rhs.__pMatrix[i][j];
186 DoubleMatrix::Equals(const Tizen::Base::Object& obj) const
188 const DoubleMatrix* pOther = dynamic_cast <const DoubleMatrix*>(&obj);
195 return (*this == *pOther);
199 DoubleMatrix::GetHashCode(void) const
202 for (int i = 0; i < __row; i++)
204 for (int j = 0; j < __column; j++)
206 hash = hash + Tizen::Base::Double::GetHashCode(__pMatrix[i][j]);
214 DoubleMatrix::Add(const DoubleMatrix& matrix)
216 SysTryReturnResult(NID_BASE, (__row == matrix.__row) && (__column == matrix.__column), E_INVALID_ARG,
217 "Either row or column count of the current instance is not same with that of the specified instance.");
219 for (int i = 0; i < __row; i++)
221 for (int j = 0; j < __column; j++)
223 __pMatrix[i][j] = __pMatrix[i][j] + matrix.__pMatrix[i][j];
231 DoubleMatrix::AddToEachElement(double value)
233 for (int i = 0; i < __row; i++)
235 for (int j = 0; j < __column; j++)
237 __pMatrix[i][j] = __pMatrix[i][j] + value;
243 DoubleMatrix::AllocateCapacity(int rowCount, int columnCount)
245 std::unique_ptr<double* []> pMatrix(new (std::nothrow) double* [rowCount]);
246 SysTryReturn(NID_BASE, pMatrix != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
247 GetErrorMessage(E_OUT_OF_MEMORY));
249 for ( int i = 0 ; i < rowCount ; i++ )
251 pMatrix[i] = new (std::nothrow) double[columnCount];
252 if (pMatrix[i] == null)
254 for (int j = 0; j < i; j++)
262 __pMatrix = pMatrix.release();
268 DoubleMatrix::CalculateDeterminant(double** pMatrix, int order) const // For perfomance, we have to change the logic of recursive to LU decomposition.
270 SysTryReturn(NID_BASE, pMatrix != null, 0.0f, E_INVALID_ARG, "[%s] Invalid argument is used. pMatrix is null.",
271 GetErrorMessage(E_INVALID_ARG));
275 return pMatrix[0][0];
278 double determinant = 0.0f;
279 std::unique_ptr<double* []> pMinor(new (std::nothrow) double* [order - 1]);
280 SysTryReturn(NID_BASE, pMinor != null, determinant, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
281 GetErrorMessage(E_OUT_OF_MEMORY));
282 for (int i = 0; i < order - 1; i++)
284 pMinor[i] = new (std::nothrow) double[order - 1];
285 if (pMinor[i] == null)
287 for (int j = 0; j < i; j++)
295 bool signFlag = true;
296 for (int i = 0; i < order; i++)
298 GetMinor(pMatrix, pMinor.get(), 0, i, order);
300 if (signFlag == true)
302 determinant += pMatrix[0][i] * CalculateDeterminant(pMinor.get(), order - 1);
307 determinant += -pMatrix[0][i] * CalculateDeterminant(pMinor.get(), order - 1);
312 for (int i = 0; i < order - 1; i++)
321 DoubleMatrix::GetColumnCount(void) const
327 DoubleMatrix::GetColumnN(int columnIndex) const
329 SysTryReturn(NID_BASE, columnIndex <= __column, null, E_INVALID_ARG,
330 "[%s] Invalid argument is used. The columnIndex is larger than the column count of the current instance.",
331 GetErrorMessage(E_INVALID_ARG));
333 std::unique_ptr<double []> pColumn(new (std::nothrow) double [__row]);
334 SysTryReturn(NID_BASE, pColumn != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
335 GetErrorMessage(E_OUT_OF_MEMORY));
337 for (int i = 0; i < __row; i++)
339 pColumn[i] = __pMatrix[i][columnIndex];
342 return pColumn.release();
346 DoubleMatrix::GetDeterminant(void) const
348 SysTryReturn(NID_BASE, __row == __column, 0.0f, E_INVALID_OPERATION,
349 "[%s] The current instance is not a square matrix.", GetErrorMessage(E_INVALID_OPERATION));
351 return CalculateDeterminant(__pMatrix, __row);
355 DoubleMatrix::GetElement(int rowIndex, int columnIndex) const
357 SysTryReturn(NID_BASE, (rowIndex <= __row) && (columnIndex <= __column), 0.0f, E_INVALID_ARG,
358 "[%s] Invalid argument is used. The current instance is not a square matrix.", GetErrorMessage(E_INVALID_ARG));
360 return __pMatrix[rowIndex][columnIndex];
364 DoubleMatrix::GetInverseN(void) const
366 SysTryReturn(NID_BASE, __row == __column, null, E_INVALID_OPERATION,
367 "[%s] The current instance is not a square matrix.", GetErrorMessage(E_INVALID_OPERATION));
369 std::unique_ptr<DoubleMatrix> pInverseMatrix(new (std::nothrow) DoubleMatrix(__row, __column));
370 SysTryReturn(NID_BASE, pInverseMatrix != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
371 GetErrorMessage(E_OUT_OF_MEMORY));
373 double determinant = CalculateDeterminant(__pMatrix, __row);
375 if (Tizen::Base::Double::Compare(determinant,0.0f) == 0)
380 std::unique_ptr<double* []> pMinor(new (std::nothrow) double* [__row - 1]);
381 SysTryReturn(NID_BASE, pMinor != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
382 GetErrorMessage(E_OUT_OF_MEMORY));
384 for (int i = 0; i < __row -1; i++)
386 pMinor[i] = new (std::nothrow) double[__row - 1];
387 if (pMinor[i] == null)
389 for (int j = 0; j < i; j++)
397 for (int i = 0; i < __row; i++)
399 for (int j = 0; j < __row; j++)
401 GetMinor(__pMatrix, pMinor.get(), i, j, __row);
402 pInverseMatrix->__pMatrix[j][i] = CalculateDeterminant(pMinor.get(), __row - 1) / determinant;
403 if ((i + j + 2) % 2 == 1)
405 pInverseMatrix->__pMatrix[j][i] = -pInverseMatrix->__pMatrix[j][i];
410 for ( int i = 0 ; i < __row -1 ; i++ )
415 return pInverseMatrix.release();
419 DoubleMatrix::GetMinor(double** pSrc, double** pDest, int rowIndex, int columnIndex, int order) const
421 SysTryReturn(NID_BASE, pSrc != null, , E_INVALID_ARG, "[%s] Invalid argument is used. pSrc is null.",
422 GetErrorMessage(E_INVALID_ARG));
423 SysTryReturn(NID_BASE, pDest != null, , E_INVALID_ARG, "[%s] Invalid argument is used. pDest is null.",
424 GetErrorMessage(E_INVALID_ARG));
429 for (int i = 0; i < order; i++)
435 for (int j = 0; j < order; j++)
437 if (j != columnIndex)
439 pDest[rowCount][columnCount] = pSrc[i][j];
449 DoubleMatrix::GetRowCount(void) const
455 DoubleMatrix::GetRowN(int rowIndex) const
457 SysTryReturn(NID_BASE, rowIndex <= __row, null, E_INVALID_ARG,
458 "[%s] Invalid argument is used. The rowIndex is larger than the row count of the current instance.",
459 GetErrorMessage(E_INVALID_ARG));
461 std::unique_ptr<double []> pRow(new (std::nothrow) double [__column]);
462 SysTryReturn(NID_BASE, pRow != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
463 GetErrorMessage(E_OUT_OF_MEMORY));
465 for (int i = 0; i < __column; i++)
467 pRow[i] = __pMatrix[rowIndex][i];
470 return pRow.release();
474 DoubleMatrix::GetTrace(double& value) const
476 SysTryReturnResult(NID_BASE, __row == __column, E_INVALID_OPERATION, "The current instance is not a square matrix.");
480 for (int i = 0; i < __row; i++)
482 value += __pMatrix[i][i];
489 DoubleMatrix::GetTransposeN(void) const
491 SysTryReturn(NID_BASE, __row == __column, null, E_INVALID_OPERATION,
492 "[%s] The current instance is not a square matrix.", GetErrorMessage(E_INVALID_OPERATION));
494 std::unique_ptr<DoubleMatrix> pTransposeMatrix(new (std::nothrow) DoubleMatrix(*this));
495 SysTryReturn(NID_BASE, pTransposeMatrix != null, null, E_OUT_OF_MEMORY,
496 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
500 for (int i = 0; i < __row; i++)
502 for (int j = 0; j < columnIndex; j++)
504 double temp = pTransposeMatrix->__pMatrix[i][j];
505 pTransposeMatrix->__pMatrix[i][j] = pTransposeMatrix->__pMatrix[j][i];
506 pTransposeMatrix->__pMatrix[j][i] = temp;
512 return pTransposeMatrix.release();
516 DoubleMatrix::IsIdentity(void) const
518 if (__row != __column)
523 for (int i = 0; i < __row; i++)
525 for (int j = 0; j < __column; j++)
529 if (Tizen::Base::Double::Compare(__pMatrix[i][j],1.0f) != 0)
536 if (Tizen::Base::Double::Compare(__pMatrix[i][j],0.0f) != 0)
549 DoubleMatrix::IsInvertible(void) const
551 int ret = Tizen::Base::Double::Compare(GetDeterminant(),0.0f);
564 DoubleMatrix::Multiply(const DoubleMatrix& matrix)
566 SysTryReturnResult(NID_BASE, __column == matrix.__row, E_INVALID_ARG,
567 "The column count of the current instance is not same with the row count of the specified instance.");
569 std::unique_ptr<double* []> pResult(new (std::nothrow) double* [__row]);
570 SysTryReturnResult(NID_BASE, pResult != null, E_OUT_OF_MEMORY, "Allocating memory is failed.");
572 for ( int i = 0 ; i < __row ; i++ )
574 pResult[i] = new (std::nothrow) double[matrix.__column];
575 if (pResult[i] == null)
577 for (int j = 0; j < i; j++)
581 return E_OUT_OF_MEMORY;
585 for (int i = 0; i < __row; i++)
587 for (int j = 0; j < matrix.__column; j++)
589 pResult[i][j] = 0.0f;
591 for (int k = 0; k < __column; k++)
593 pResult[i][j] += __pMatrix[i][k] * matrix.__pMatrix[k][j];
598 for ( int i = 0 ; i < __row ; i++ )
600 delete[] __pMatrix[i];
605 __pMatrix = pResult.release();
611 DoubleMatrix::Multiply(double value)
613 for (int i = 0; i < __row; i++)
615 for (int j = 0; j < __column; j++)
617 __pMatrix[i][j] = __pMatrix[i][j] * value;
623 DoubleMatrix::Negate(void)
625 for (int i = 0; i < __row; i++)
627 for (int j = 0; j < __column; j++)
629 __pMatrix[i][j] = -__pMatrix[i][j];
635 DoubleMatrix::SetAsIdentity(void)
637 SysTryReturnResult(NID_BASE, __row == __column, E_INVALID_OPERATION, "The current instance is not a square matrix.");
639 for (int i = 0; i < __row; i++)
641 for (int j = 0; j < __column; j++)
645 __pMatrix[i][j] = 1.0f;
649 __pMatrix[i][j] = 0.0f;
658 DoubleMatrix::Invert(void)
660 SysTryReturnResult(NID_BASE, __row == __column, E_INVALID_OPERATION, "The current instance is not a square matrix.");
662 double determinant = CalculateDeterminant(__pMatrix, __row);
663 SysTryReturnResult(NID_BASE, Tizen::Base::Double::Compare(determinant, 0.0f) != 0, E_INVALID_OPERATION,
664 "The current instance is not invertible.");
666 std::unique_ptr<double* []> pInverse(new (std::nothrow) double* [__row]);
667 SysTryReturnResult(NID_BASE, pInverse != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
668 GetErrorMessage(E_OUT_OF_MEMORY));
670 for (int i = 0; i < __row; i++)
672 pInverse[i] = new (std::nothrow) double[__row];
673 if (pInverse[i] == null)
675 for (int j = 0; j < i; j++)
677 delete[] pInverse[j];
679 return E_OUT_OF_MEMORY;
683 std::unique_ptr<double* []> pMinor(new (std::nothrow) double* [__row - 1]);
686 for ( int i = 0 ; i < __row ; i++ )
688 delete[] pInverse[i];
690 return E_OUT_OF_MEMORY;
693 for (int i = 0; i < __row -1; i++)
695 pMinor[i] = new double[__row - 1];
696 if (pMinor[i] == null)
698 for( int i = 0 ; i < __row ; i++ )
700 delete[] pInverse[i];
703 for (int j = 0; j < i; j++)
707 return E_OUT_OF_MEMORY;
711 for (int i = 0; i < __row; i++)
713 for (int j = 0; j < __row; j++)
715 GetMinor(__pMatrix, pMinor.get(), i, j, __row);
716 pInverse[j][i] = CalculateDeterminant(pMinor.get(), __row - 1) / determinant;
717 if ((i +j +2) % 2 == 1)
719 pInverse[j][i] = -pInverse[j][i];
724 for ( int i = 0 ; i < __row ; i++ )
726 delete[] __pMatrix[i];
730 __pMatrix = pInverse.release();
732 for (int i = 0 ; i < __row -1; i++ )
741 DoubleMatrix::Transpose(void)
743 SysTryReturnResult(NID_BASE, __row == __column, E_INVALID_OPERATION, "The current instance is not a square matrix.");
747 for (int i = 0; i < __row; i++)
749 for (int j = 0; j < columnIndex; j++)
751 double temp = __pMatrix[i][j];
752 __pMatrix[i][j] = __pMatrix[j][i];
753 __pMatrix[j][i] = temp;
763 DoubleMatrix::SetColumn(int columnIndex, const double* pArray)
765 SysTryReturnResult(NID_BASE, pArray != null, E_INVALID_ARG, "pArray is null");
766 SysTryReturnResult(NID_BASE, columnIndex <= __column, E_INVALID_ARG,
767 "columnIndex is larger than the column count of the current instance.");
769 for (int i = 0; i < __row; i++)
771 __pMatrix[i][columnIndex] = pArray[i];
778 DoubleMatrix::SetRow(int rowIndex, const double* pArray)
780 SysTryReturnResult(NID_BASE, pArray != null, E_INVALID_ARG, "pArray is null");
781 SysTryReturnResult(NID_BASE, rowIndex <= __row, E_INVALID_ARG,
782 "rowIndex is larger than the row count of the current instance.");
784 for (int i = 0; i < __column; i++)
786 __pMatrix[rowIndex][i] = pArray[i];
793 DoubleMatrix::SetElement(int rowIndex, int columnIndex, double value)
795 SysTryReturnResult(NID_BASE, columnIndex <= __column, E_INVALID_ARG,
796 "columnIndex is larger than the column count of the current instance.");
797 SysTryReturnResult(NID_BASE, rowIndex <= __row, E_INVALID_ARG,
798 "rowIndex is larger than the row count of the current instance.");
800 __pMatrix[rowIndex][columnIndex] = value;
806 DoubleMatrix::SetValue(const double* pArray, bool rowMajor)
808 SysTryReturnResult(NID_BASE, pArray != null, E_INVALID_ARG, "pArray is null.");
810 if (rowMajor == true)
812 for (int i = 0; i < __row; i++)
814 for (int j = 0; j < __column; j++)
816 __pMatrix[i][j] = pArray[i * __row + j];
822 for (int i = 0; i < __column; i++)
824 for (int j = 0; j < __row; j++)
826 __pMatrix[j][i] = pArray[i * __column + j];
835 DoubleMatrix::SetAsNull(void)
837 for (int i = 0; i < __row; i++)
839 for (int j = 0; j < __column; j++)
841 __pMatrix[i][j] = 0.0f;
847 DoubleMatrix::Subtract(const DoubleMatrix& matrix)
849 SysTryReturnResult(NID_BASE, (__row == matrix.__row) && (__column == matrix.__column), E_INVALID_ARG,
850 "Either row or column count of the current instance is not same with that of the specified instance.");
852 for (int i = 0; i < __row; i++)
854 for (int j = 0; j < __column; j++)
856 __pMatrix[i][j] = __pMatrix[i][j] - matrix.__pMatrix[i][j];
864 DoubleMatrix::SubtractToEachElement(double value)
866 for (int i = 0; i < __row; i++)
868 for (int j = 0; j < __column; j++)
870 __pMatrix[i][j] = __pMatrix[i][j] - value;