2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
18 * @file FBaseDoubleMatrix.cpp
19 * @brief This is the implementation for DoubleMatrix class.
21 #include <FBaseDoubleMatrix.h>
22 #include <FBaseSysLog.h>
23 #include <unique_ptr.h>
25 namespace Tizen { namespace Base
28 DoubleMatrix::DoubleMatrix(void)
36 DoubleMatrix::DoubleMatrix(const DoubleMatrix& rhs)
39 , __column(rhs.__column)
41 AllocateCapacity(__row, __column);
42 for (int i = 0; i < __row; i++)
44 for (int j = 0; j < __column; j++)
46 __pMatrix[i][j] = rhs.__pMatrix[i][j];
51 DoubleMatrix::DoubleMatrix(int rowCount, int columnCount)
54 , __column(columnCount)
56 AllocateCapacity(__row, __column);
60 DoubleMatrix::DoubleMatrix(int rowCount, int columnCount, const double* pArray, bool rowMajor)
63 , __column(columnCount)
65 AllocateCapacity(__row, __column);
70 for (int i = 0; i < __row; i++)
72 for (int j = 0; j < __column; j++)
74 __pMatrix[i][j] = pArray[i * __column + j];
80 for (int i = 0; i < __column; i++)
82 for (int j = 0; j < __row; j++)
84 __pMatrix[j][i] = pArray[i * __row + j];
95 DoubleMatrix::DoubleMatrix(int rowCount, int columnCount, const double* pArray[])
98 , __column(columnCount)
100 AllocateCapacity(__row, __column);
103 for (int i = 0; i < __row; i++)
105 for (int j = 0; j < __column; j++)
107 __pMatrix[i][j] = pArray[i][j];
117 DoubleMatrix::~DoubleMatrix(void)
119 for (int i = 0; i < __row; i++)
121 delete[] __pMatrix[i];
128 DoubleMatrix::operator ==(const DoubleMatrix& rhs) const
135 if ((__row != rhs.__row) || (__column != rhs.__column))
140 for (int i = 0; i < __row; i++)
142 for (int j = 0; j < __column; j++)
144 if (__pMatrix[i][j] != rhs.__pMatrix[i][j])
155 DoubleMatrix::operator !=(const DoubleMatrix& rhs) const
157 return !(*this == rhs);
161 DoubleMatrix::operator =(const DoubleMatrix& rhs)
168 SysTryReturn(NID_BASE, (__row == rhs.__row) && (__column == rhs.__column), *this, E_INVALID_ARG,
169 "[%s] Invalid argument is used. Either row or column count of the current instance is not same with that of the specified instance.",
170 GetErrorMessage(E_INVALID_ARG));
172 for (int i = 0; i < __row; i++)
174 for (int j = 0; j < __column; j++)
176 __pMatrix[i][j] = rhs.__pMatrix[i][j];
184 DoubleMatrix::Equals(const Tizen::Base::Object& obj) const
186 const DoubleMatrix* pOther = dynamic_cast< const DoubleMatrix* >(&obj);
193 return (*this == *pOther);
197 DoubleMatrix::GetHashCode(void) const
200 for (int i = 0; i < __row; i++)
202 for (int j = 0; j < __column; j++)
204 hash = hash + Tizen::Base::Double::GetHashCode(__pMatrix[i][j]);
212 DoubleMatrix::Add(const DoubleMatrix& matrix)
214 SysTryReturnResult(NID_BASE, (__row == matrix.__row) && (__column == matrix.__column), E_INVALID_ARG,
215 "Either row or column count of the current instance is not same with that of the specified instance.");
217 for (int i = 0; i < __row; i++)
219 for (int j = 0; j < __column; j++)
221 __pMatrix[i][j] = __pMatrix[i][j] + matrix.__pMatrix[i][j];
229 DoubleMatrix::AddToEachElement(double value)
231 for (int i = 0; i < __row; i++)
233 for (int j = 0; j < __column; j++)
235 __pMatrix[i][j] = __pMatrix[i][j] + value;
241 DoubleMatrix::AllocateCapacity(int rowCount, int columnCount)
243 std::unique_ptr< double*[] > pMatrix(new (std::nothrow) double*[rowCount]);
244 SysTryReturn(NID_BASE, pMatrix != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
245 GetErrorMessage(E_OUT_OF_MEMORY));
247 for (int i = 0; i < rowCount; i++)
249 pMatrix[i] = new (std::nothrow) double[columnCount];
250 if (pMatrix[i] == null)
252 for (int j = 0; j < i; j++)
260 __pMatrix = pMatrix.release();
266 DoubleMatrix::CalculateDeterminant(double** pMatrix, int order) const // For perfomance, we have to change the logic of recursive to LU decomposition.
268 SysTryReturn(NID_BASE, pMatrix != null, 0.0f, E_INVALID_ARG, "[%s] Invalid argument is used. pMatrix is null.",
269 GetErrorMessage(E_INVALID_ARG));
273 return pMatrix[0][0];
276 double determinant = 0.0f;
277 std::unique_ptr< double*[] > pMinor(new (std::nothrow) double*[order - 1]);
278 SysTryReturn(NID_BASE, pMinor != null, determinant, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
279 GetErrorMessage(E_OUT_OF_MEMORY));
280 for (int i = 0; i < order - 1; i++)
282 pMinor[i] = new (std::nothrow) double[order - 1];
283 if (pMinor[i] == null)
285 for (int j = 0; j < i; j++)
293 bool signFlag = true;
294 for (int i = 0; i < order; i++)
296 GetMinor(pMatrix, pMinor.get(), 0, i, order);
298 if (signFlag == true)
300 determinant += pMatrix[0][i] * CalculateDeterminant(pMinor.get(), order - 1);
305 determinant += -pMatrix[0][i] * CalculateDeterminant(pMinor.get(), order - 1);
310 for (int i = 0; i < order - 1; i++)
319 DoubleMatrix::GetColumnCount(void) const
325 DoubleMatrix::GetColumnN(int columnIndex) const
327 SysTryReturn(NID_BASE, columnIndex <= __column, null, E_INVALID_ARG,
328 "[%s] Invalid argument is used. The columnIndex is larger than the column count of the current instance.",
329 GetErrorMessage(E_INVALID_ARG));
331 std::unique_ptr< double[] > pColumn(new (std::nothrow) double[__row]);
332 SysTryReturn(NID_BASE, pColumn != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
333 GetErrorMessage(E_OUT_OF_MEMORY));
335 for (int i = 0; i < __row; i++)
337 pColumn[i] = __pMatrix[i][columnIndex];
340 return pColumn.release();
344 DoubleMatrix::GetDeterminant(void) const
346 SysTryReturn(NID_BASE, __row == __column, 0.0f, E_INVALID_OPERATION,
347 "[%s] The current instance is not a square matrix.", GetErrorMessage(E_INVALID_OPERATION));
349 return CalculateDeterminant(__pMatrix, __row);
353 DoubleMatrix::GetElement(int rowIndex, int columnIndex) const
355 SysTryReturn(NID_BASE, (rowIndex <= __row) && (columnIndex <= __column), 0.0f, E_INVALID_ARG,
356 "[%s] Invalid argument is used. The current instance is not a square matrix.", GetErrorMessage(E_INVALID_ARG));
358 return __pMatrix[rowIndex][columnIndex];
362 DoubleMatrix::GetInverseN(void) const
364 SysTryReturn(NID_BASE, __row == __column, null, E_INVALID_OPERATION,
365 "[%s] The current instance is not a square matrix.", GetErrorMessage(E_INVALID_OPERATION));
367 std::unique_ptr< DoubleMatrix > pInverseMatrix(new (std::nothrow) DoubleMatrix(__row, __column));
368 SysTryReturn(NID_BASE, pInverseMatrix != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
369 GetErrorMessage(E_OUT_OF_MEMORY));
371 double determinant = CalculateDeterminant(__pMatrix, __row);
373 if (Tizen::Base::Double::Compare(determinant, 0.0f) == 0)
378 std::unique_ptr< double*[] > pMinor(new (std::nothrow) double*[__row - 1]);
379 SysTryReturn(NID_BASE, pMinor != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
380 GetErrorMessage(E_OUT_OF_MEMORY));
382 for (int i = 0; i < __row - 1; i++)
384 pMinor[i] = new (std::nothrow) double[__row - 1];
385 if (pMinor[i] == null)
387 for (int j = 0; j < i; j++)
395 for (int i = 0; i < __row; i++)
397 for (int j = 0; j < __row; j++)
399 GetMinor(__pMatrix, pMinor.get(), i, j, __row);
400 pInverseMatrix->__pMatrix[j][i] = CalculateDeterminant(pMinor.get(), __row - 1) / determinant;
401 if ((i + j + 2) % 2 == 1)
403 pInverseMatrix->__pMatrix[j][i] = -pInverseMatrix->__pMatrix[j][i];
408 for (int i = 0; i < __row - 1; i++)
413 return pInverseMatrix.release();
417 DoubleMatrix::GetMinor(double** pSrc, double** pDest, int rowIndex, int columnIndex, int order) const
419 SysTryReturn(NID_BASE, pSrc != null, , E_INVALID_ARG, "[%s] Invalid argument is used. pSrc is null.",
420 GetErrorMessage(E_INVALID_ARG));
421 SysTryReturn(NID_BASE, pDest != null, , E_INVALID_ARG, "[%s] Invalid argument is used. pDest is null.",
422 GetErrorMessage(E_INVALID_ARG));
427 for (int i = 0; i < order; i++)
433 for (int j = 0; j < order; j++)
435 if (j != columnIndex)
437 pDest[rowCount][columnCount] = pSrc[i][j];
447 DoubleMatrix::GetRowCount(void) const
453 DoubleMatrix::GetRowN(int rowIndex) const
455 SysTryReturn(NID_BASE, rowIndex <= __row, null, E_INVALID_ARG,
456 "[%s] Invalid argument is used. The rowIndex is larger than the row count of the current instance.",
457 GetErrorMessage(E_INVALID_ARG));
459 std::unique_ptr< double[] > pRow(new (std::nothrow) double[__column]);
460 SysTryReturn(NID_BASE, pRow != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
461 GetErrorMessage(E_OUT_OF_MEMORY));
463 for (int i = 0; i < __column; i++)
465 pRow[i] = __pMatrix[rowIndex][i];
468 return pRow.release();
472 DoubleMatrix::GetTrace(double& value) const
474 SysTryReturnResult(NID_BASE, __row == __column, E_INVALID_OPERATION, "The current instance is not a square matrix.");
478 for (int i = 0; i < __row; i++)
480 value += __pMatrix[i][i];
487 DoubleMatrix::GetTransposeN(void) const
489 SysTryReturn(NID_BASE, __row == __column, null, E_INVALID_OPERATION,
490 "[%s] The current instance is not a square matrix.", GetErrorMessage(E_INVALID_OPERATION));
492 std::unique_ptr< DoubleMatrix > pTransposeMatrix(new (std::nothrow) DoubleMatrix(*this));
493 SysTryReturn(NID_BASE, pTransposeMatrix != null, null, E_OUT_OF_MEMORY,
494 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
498 for (int i = 0; i < __row; i++)
500 for (int j = 0; j < columnIndex; j++)
502 double temp = pTransposeMatrix->__pMatrix[i][j];
503 pTransposeMatrix->__pMatrix[i][j] = pTransposeMatrix->__pMatrix[j][i];
504 pTransposeMatrix->__pMatrix[j][i] = temp;
510 return pTransposeMatrix.release();
514 DoubleMatrix::IsIdentity(void) const
516 if (__row != __column)
521 for (int i = 0; i < __row; i++)
523 for (int j = 0; j < __column; j++)
527 if (Tizen::Base::Double::Compare(__pMatrix[i][j], 1.0f) != 0)
534 if (Tizen::Base::Double::Compare(__pMatrix[i][j], 0.0f) != 0)
547 DoubleMatrix::IsInvertible(void) const
549 int ret = Tizen::Base::Double::Compare(GetDeterminant(), 0.0f);
562 DoubleMatrix::Multiply(const DoubleMatrix& matrix)
564 SysTryReturnResult(NID_BASE, __column == matrix.__row, E_INVALID_ARG,
565 "The column count of the current instance is not same with the row count of the specified instance.");
567 std::unique_ptr< double*[] > pResult(new (std::nothrow) double*[__row]);
568 SysTryReturnResult(NID_BASE, pResult != null, E_OUT_OF_MEMORY, "Allocating memory is failed.");
570 for (int i = 0; i < __row; i++)
572 pResult[i] = new (std::nothrow) double[matrix.__column];
573 if (pResult[i] == null)
575 for (int j = 0; j < i; j++)
579 return E_OUT_OF_MEMORY;
583 for (int i = 0; i < __row; i++)
585 for (int j = 0; j < matrix.__column; j++)
587 pResult[i][j] = 0.0f;
589 for (int k = 0; k < __column; k++)
591 pResult[i][j] += __pMatrix[i][k] * matrix.__pMatrix[k][j];
596 for (int i = 0; i < __row; i++)
598 delete[] __pMatrix[i];
603 __pMatrix = pResult.release();
609 DoubleMatrix::Multiply(double value)
611 for (int i = 0; i < __row; i++)
613 for (int j = 0; j < __column; j++)
615 __pMatrix[i][j] = __pMatrix[i][j] * value;
621 DoubleMatrix::Negate(void)
623 for (int i = 0; i < __row; i++)
625 for (int j = 0; j < __column; j++)
627 __pMatrix[i][j] = -__pMatrix[i][j];
633 DoubleMatrix::SetAsIdentity(void)
635 SysTryReturnResult(NID_BASE, __row == __column, E_INVALID_OPERATION, "The current instance is not a square matrix.");
637 for (int i = 0; i < __row; i++)
639 for (int j = 0; j < __column; j++)
643 __pMatrix[i][j] = 1.0f;
647 __pMatrix[i][j] = 0.0f;
656 DoubleMatrix::Invert(void)
658 SysTryReturnResult(NID_BASE, __row == __column, E_INVALID_OPERATION, "The current instance is not a square matrix.");
660 double determinant = CalculateDeterminant(__pMatrix, __row);
661 SysTryReturnResult(NID_BASE, Tizen::Base::Double::Compare(determinant, 0.0f) != 0, E_INVALID_OPERATION,
662 "The current instance is not invertible.");
664 std::unique_ptr< double*[] > pInverse(new (std::nothrow) double*[__row]);
665 SysTryReturnResult(NID_BASE, pInverse != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
666 GetErrorMessage(E_OUT_OF_MEMORY));
668 for (int i = 0; i < __row; i++)
670 pInverse[i] = new (std::nothrow) double[__row];
671 if (pInverse[i] == null)
673 for (int j = 0; j < i; j++)
675 delete[] pInverse[j];
677 return E_OUT_OF_MEMORY;
681 std::unique_ptr< double*[] > pMinor(new (std::nothrow) double*[__row - 1]);
684 for (int i = 0; i < __row; i++)
686 delete[] pInverse[i];
688 return E_OUT_OF_MEMORY;
691 for (int i = 0; i < __row - 1; i++)
693 pMinor[i] = new double[__row - 1];
694 if (pMinor[i] == null)
696 for (int k = 0; k < __row; k++)
698 delete[] pInverse[k];
701 for (int j = 0; j < i; j++)
705 return E_OUT_OF_MEMORY;
709 for (int i = 0; i < __row; i++)
711 for (int j = 0; j < __row; j++)
713 GetMinor(__pMatrix, pMinor.get(), i, j, __row);
714 pInverse[j][i] = CalculateDeterminant(pMinor.get(), __row - 1) / determinant;
715 if ((i + j + 2) % 2 == 1)
717 pInverse[j][i] = -pInverse[j][i];
722 for (int i = 0; i < __row; i++)
724 delete[] __pMatrix[i];
728 __pMatrix = pInverse.release();
730 for (int i = 0; i < __row - 1; i++)
739 DoubleMatrix::Transpose(void)
741 SysTryReturnResult(NID_BASE, __row == __column, E_INVALID_OPERATION, "The current instance is not a square matrix.");
745 for (int i = 0; i < __row; i++)
747 for (int j = 0; j < columnIndex; j++)
749 double temp = __pMatrix[i][j];
750 __pMatrix[i][j] = __pMatrix[j][i];
751 __pMatrix[j][i] = temp;
761 DoubleMatrix::SetColumn(int columnIndex, const double* pArray)
763 SysTryReturnResult(NID_BASE, pArray != null, E_INVALID_ARG, "pArray is null");
764 SysTryReturnResult(NID_BASE, columnIndex <= __column, E_INVALID_ARG,
765 "columnIndex is larger than the column count of the current instance.");
767 for (int i = 0; i < __row; i++)
769 __pMatrix[i][columnIndex] = pArray[i];
776 DoubleMatrix::SetRow(int rowIndex, const double* pArray)
778 SysTryReturnResult(NID_BASE, pArray != null, E_INVALID_ARG, "pArray is null");
779 SysTryReturnResult(NID_BASE, rowIndex <= __row, E_INVALID_ARG,
780 "rowIndex is larger than the row count of the current instance.");
782 for (int i = 0; i < __column; i++)
784 __pMatrix[rowIndex][i] = pArray[i];
791 DoubleMatrix::SetElement(int rowIndex, int columnIndex, double value)
793 SysTryReturnResult(NID_BASE, columnIndex <= __column, E_INVALID_ARG,
794 "columnIndex is larger than the column count of the current instance.");
795 SysTryReturnResult(NID_BASE, rowIndex <= __row, E_INVALID_ARG,
796 "rowIndex is larger than the row count of the current instance.");
798 __pMatrix[rowIndex][columnIndex] = value;
804 DoubleMatrix::SetValue(const double* pArray, bool rowMajor)
806 SysTryReturnResult(NID_BASE, pArray != null, E_INVALID_ARG, "pArray is null.");
808 if (rowMajor == true)
810 for (int i = 0; i < __row; i++)
812 for (int j = 0; j < __column; j++)
814 __pMatrix[i][j] = pArray[i * __column + j];
820 for (int i = 0; i < __column; i++)
822 for (int j = 0; j < __row; j++)
824 __pMatrix[j][i] = pArray[i * __row + j];
833 DoubleMatrix::SetAsNull(void)
835 for (int i = 0; i < __row; i++)
837 for (int j = 0; j < __column; j++)
839 __pMatrix[i][j] = 0.0f;
845 DoubleMatrix::Subtract(const DoubleMatrix& matrix)
847 SysTryReturnResult(NID_BASE, (__row == matrix.__row) && (__column == matrix.__column), E_INVALID_ARG,
848 "Either row or column count of the current instance is not same with that of the specified instance.");
850 for (int i = 0; i < __row; i++)
852 for (int j = 0; j < __column; j++)
854 __pMatrix[i][j] = __pMatrix[i][j] - matrix.__pMatrix[i][j];
862 DoubleMatrix::SubtractToEachElement(double value)
864 for (int i = 0; i < __row; i++)
866 for (int j = 0; j < __column; j++)
868 __pMatrix[i][j] = __pMatrix[i][j] - value;