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 FBaseFloatMatrix.cpp
19 * @brief This is the implementation for FloatMatrix class.
22 #include <FBaseFloatMatrix.h>
23 #include <FBaseSysLog.h>
24 #include <unique_ptr.h>
26 namespace Tizen { namespace Base
29 FloatMatrix::FloatMatrix(void)
37 FloatMatrix::FloatMatrix(const FloatMatrix& rhs)
40 , __column(rhs.__column)
42 AllocateCapacity(__row, __column);
43 for (int i = 0; i < __row; i++)
45 for (int j = 0; j < __column; j++)
47 __pMatrix[i][j] = rhs.__pMatrix[i][j];
52 FloatMatrix::FloatMatrix(int rowCount, int columnCount)
55 , __column(columnCount)
57 AllocateCapacity(__row, __column);
61 FloatMatrix::FloatMatrix(int rowCount, int columnCount, const float* pArray, bool rowMajor)
64 , __column(columnCount)
66 AllocateCapacity(__row, __column);
71 for (int i = 0; i < __row; i++)
73 for (int j = 0; j < __column; j++)
75 __pMatrix[i][j] = pArray[i * __column + j];
81 for (int i = 0; i < __column; i++)
83 for (int j = 0; j < __row; j++)
85 __pMatrix[j][i] = pArray[i * __row + j];
96 FloatMatrix::FloatMatrix(int rowCount, int columnCount, const float* pArray[])
99 , __column(columnCount)
101 AllocateCapacity(__row, __column);
104 for (int i = 0; i < __row; i++)
106 for (int j = 0; j < __column; j++)
108 __pMatrix[i][j] = pArray[i][j];
118 FloatMatrix::~FloatMatrix(void)
120 for ( int i = 0 ; i < __row ; i++ )
122 delete[] __pMatrix[i];
129 FloatMatrix::operator ==(const FloatMatrix& rhs) const
136 if ((__row != rhs.__row) || (__column != rhs.__column))
141 for (int i = 0; i < __row; i++)
143 for (int j = 0; j < __column; j++)
145 if (__pMatrix[i][j] != rhs.__pMatrix[i][j])
156 FloatMatrix::operator !=(const FloatMatrix& rhs) const
158 return !(*this == rhs);
162 FloatMatrix::operator =(const FloatMatrix& rhs)
169 SysTryReturn(NID_BASE, (__row == rhs.__row) && (__column == rhs.__column), *this, E_INVALID_ARG,
170 "[%s] Invalid argument is used. Either row or column count of the current instance is not same with that of the specified instance.",
171 GetErrorMessage(E_INVALID_ARG));
173 for (int i = 0; i < __row; i++)
175 for (int j = 0; j < __column; j++)
177 __pMatrix[i][j] = rhs.__pMatrix[i][j];
185 FloatMatrix::Equals(const Tizen::Base::Object& obj) const
187 const FloatMatrix* pOther = dynamic_cast <const FloatMatrix*>(&obj);
194 return (*this == *pOther);
198 FloatMatrix::GetHashCode(void) const
201 for (int i = 0; i < __row; i++)
203 for (int j = 0; j < __column; j++)
205 hash = hash + Tizen::Base::Float::GetHashCode(__pMatrix[i][j]);
213 FloatMatrix::Add(const FloatMatrix& matrix)
215 SysTryReturnResult(NID_BASE, (__row == matrix.__row) && (__column == matrix.__column), E_INVALID_ARG,
216 "Either row or column count of the current instance is not same with that of the specified instance.");
218 for (int i = 0; i < __row; i++)
220 for (int j = 0; j < __column; j++)
222 __pMatrix[i][j] = __pMatrix[i][j] + matrix.__pMatrix[i][j];
230 FloatMatrix::AddToEachElement(float value)
232 for (int i = 0; i < __row; i++)
234 for (int j = 0; j < __column; j++)
236 __pMatrix[i][j] = __pMatrix[i][j] + value;
242 FloatMatrix::AllocateCapacity(int rowCount, int columnCount)
244 std::unique_ptr<float* []> pMatrix(new (std::nothrow) float* [rowCount]);
245 SysTryReturn(NID_BASE, pMatrix != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
246 GetErrorMessage(E_OUT_OF_MEMORY));
248 for ( int i = 0 ; i < rowCount ; i++ )
250 pMatrix[i] = new (std::nothrow) float[columnCount];
251 if (pMatrix[i] == null)
253 for (int j = 0; j < i; j++)
261 __pMatrix = pMatrix.release();
267 FloatMatrix::CalculateDeterminant(float** pMatrix, int order) const // For perfomance, we have to change the logic of recursive to LU decomposition.
269 SysTryReturn(NID_BASE, pMatrix != null, 0.0f, E_INVALID_ARG, "[%s] Invalid argument is used. pMatrix is null.",
270 GetErrorMessage(E_INVALID_ARG));
274 return pMatrix[0][0];
277 float determinant = 0.0f;
278 std::unique_ptr<float* []> pMinor(new (std::nothrow) float* [order - 1]);
279 SysTryReturn(NID_BASE, pMinor != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
280 GetErrorMessage(E_OUT_OF_MEMORY));
281 for (int i = 0; i < order - 1; i++)
283 pMinor[i] = new (std::nothrow) float[order - 1];
284 if (pMinor[i] == null)
286 for (int j = 0; j < i; j++)
294 bool signFlag = true;
295 for (int i = 0; i < order; i++)
297 GetMinor(pMatrix, pMinor.get(), 0, i, order);
299 if (signFlag == true)
301 determinant += pMatrix[0][i] * CalculateDeterminant(pMinor.get(), order - 1);
306 determinant += -pMatrix[0][i] * CalculateDeterminant(pMinor.get(), order - 1);
311 for (int i = 0; i < order - 1; i++)
320 FloatMatrix::GetColumnCount(void) const
326 FloatMatrix::GetColumnN(int columnIndex) const
328 SysTryReturn(NID_BASE, columnIndex <= __column, null, E_INVALID_ARG,
329 "[%s] Invalid argument is used. The columnIndex is larger than the column count of the current instance.",
330 GetErrorMessage(E_INVALID_ARG));
332 std::unique_ptr<float []> pColumn(new (std::nothrow) float [__row]);
333 SysTryReturn(NID_BASE, pColumn != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
334 GetErrorMessage(E_OUT_OF_MEMORY));
336 for (int i = 0; i < __row; i++)
338 pColumn[i] = __pMatrix[i][columnIndex];
341 return pColumn.release();
345 FloatMatrix::GetDeterminant(void) const
347 SysTryReturn(NID_BASE, __row == __column, 0.0f, E_INVALID_OPERATION,
348 "[%s] The current instance is not a square matrix.", GetErrorMessage(E_INVALID_OPERATION));
350 return CalculateDeterminant(__pMatrix, __row);
354 FloatMatrix::GetElement(int rowIndex, int columnIndex) const
356 SysTryReturn(NID_BASE, (rowIndex <= __row) && (columnIndex <= __column), 0.0f, E_INVALID_ARG,
357 "[%s] Invalid argument is used. The current instance is not a square matrix.", GetErrorMessage(E_INVALID_ARG));
359 return __pMatrix[rowIndex][columnIndex];
363 FloatMatrix::GetInverseN(void) const
365 SysTryReturn(NID_BASE, __row == __column, null, E_INVALID_OPERATION,
366 "[%s] The current instance is not a square matrix.", GetErrorMessage(E_INVALID_OPERATION));
368 std::unique_ptr<FloatMatrix> pInverseMatrix(new (std::nothrow) FloatMatrix(__row, __column));
369 SysTryReturn(NID_BASE, pInverseMatrix != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
370 GetErrorMessage(E_OUT_OF_MEMORY));
372 float determinant = CalculateDeterminant(__pMatrix, __row);
374 if (Tizen::Base::Float::Compare(determinant,0.0f) == 0)
379 std::unique_ptr<float* []> pMinor(new (std::nothrow) float* [__row - 1]);
380 SysTryReturn(NID_BASE, pMinor != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
381 GetErrorMessage(E_OUT_OF_MEMORY));
383 for (int i = 0; i < __row -1; i++)
385 pMinor[i] = new (std::nothrow) float[__row - 1];
386 if (pMinor[i] == null)
388 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 FloatMatrix::GetMinor(float** pSrc, float** 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.", GetErrorMessage(E_INVALID_ARG));
422 SysTryReturn(NID_BASE, pDest != null, , E_INVALID_ARG, "[%s] Invalid argument is used. pDest is null.", 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 FloatMatrix::GetRowCount(void) const
453 FloatMatrix::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<float []> pRow(new (std::nothrow) float [__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 FloatMatrix::GetTrace(float& 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 FloatMatrix::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<FloatMatrix> pTransposeMatrix(new (std::nothrow) FloatMatrix(*this));
493 SysTryReturn(NID_BASE, pTransposeMatrix != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
494 GetErrorMessage(E_OUT_OF_MEMORY));
498 for (int i = 0; i < __row; i++)
500 for (int j = 0; j < columnIndex; j++)
502 float 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 FloatMatrix::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::Float::Compare(__pMatrix[i][j],1.0f) != 0)
534 if (Tizen::Base::Float::Compare(__pMatrix[i][j],0.0f) != 0)
547 FloatMatrix::IsInvertible(void) const
549 int ret = Tizen::Base::Float::Compare(GetDeterminant(),0.0f);
562 FloatMatrix::Multiply(const FloatMatrix& 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<float* []> pResult(new (std::nothrow) float* [__row]);
568 SysTryReturnResult(NID_BASE, pResult != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
570 for ( int i = 0 ; i < __row ; i++ )
572 pResult[i] = new (std::nothrow) float[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];
602 __pMatrix = pResult.release();
608 FloatMatrix::Multiply(float value)
610 for (int i = 0; i < __row; i++)
612 for (int j = 0; j < __column; j++)
614 __pMatrix[i][j] = __pMatrix[i][j] * value;
620 FloatMatrix::Negate(void)
622 for (int i = 0; i < __row; i++)
624 for (int j = 0; j < __column; j++)
626 __pMatrix[i][j] = -__pMatrix[i][j];
632 FloatMatrix::SetAsIdentity(void)
634 SysTryReturnResult(NID_BASE, __row == __column, E_INVALID_OPERATION, "The current instance is not a square matrix.");
636 for (int i = 0; i < __row; i ++)
638 for (int j = 0; j < __column; j++)
642 __pMatrix[i][j] = 1.0f;
646 __pMatrix[i][j] = 0.0f;
655 FloatMatrix::Invert(void)
657 SysTryReturnResult(NID_BASE, __row == __column, E_INVALID_OPERATION, "The current instance is not a square matrix.");
659 float determinant = CalculateDeterminant(__pMatrix, __row);
660 SysTryReturnResult(NID_BASE, Tizen::Base::Float::Compare(determinant, 0.0f) != 0, E_INVALID_OPERATION,
661 "The current instance is not invertible.");
663 std::unique_ptr<float* []> pInverse(new (std::nothrow) float* [__row]);
664 SysTryReturn(NID_BASE, pInverse != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
665 GetErrorMessage(E_OUT_OF_MEMORY));
667 for (int i = 0; i < __row; i++)
669 pInverse[i] = new (std::nothrow) float[__row];
670 if (pInverse[i] == null)
672 for (int j = 0; j < i; j++)
674 delete[] pInverse[j];
676 return E_OUT_OF_MEMORY;
680 std::unique_ptr<float* []> pMinor(new (std::nothrow) float* [__row - 1]);
683 for ( int i = 0 ; i < __row ; i++ )
685 delete[] pInverse[i];
687 return E_OUT_OF_MEMORY;
690 for (int i = 0; i < __row - 1; i++)
692 pMinor[i] = new (std::nothrow) float[__row - 1];
693 if (pMinor[i] == null)
695 for (int k = 0 ; k < __row ; k++)
697 delete[] pInverse[k];
700 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 FloatMatrix::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 float temp = __pMatrix[i][j];
750 __pMatrix[i][j] = __pMatrix[j][i];
751 __pMatrix[j][i] = temp;
761 FloatMatrix::SetColumn(int columnIndex, const float* 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 FloatMatrix::SetRow(int rowIndex, const float* 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 FloatMatrix::SetElement(int rowIndex, int columnIndex, float 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 FloatMatrix::SetValue(const float* 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 FloatMatrix::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 FloatMatrix::Subtract(const FloatMatrix& 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 FloatMatrix::SubtractToEachElement(float 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;