#include #include #include #include #include #include #include #include namespace Poincare { template void MatrixComplexNode::didAddChildAtIndex(int newNumberOfChildren) { setNumberOfRows(1); setNumberOfColumns(newNumberOfChildren); } template std::complex MatrixComplexNode::complexAtIndex(int index) const { EvaluationNode * child = EvaluationNode::childAtIndex(index); if (child->type() == EvaluationNode::Type::Complex) { return *(static_cast *>(child)); } return std::complex(NAN, NAN); } template bool MatrixComplexNode::isUndefined() const { if (numberOfRows() != 1 || numberOfColumns() != 1) { return false; } EvaluationNode * child = const_cast *>(this)->childAtIndex(0); if (child->type() == EvaluationNode::Type::Complex && std::isnan(static_cast *>(child)->real()) && std::isnan(static_cast *>(child)->imag())) { return true; } return false; } template Expression MatrixComplexNode::complexToExpression(Preferences::ComplexFormat complexFormat) const { Matrix matrix = Matrix::EmptyMatrix(); int i = 0; for (EvaluationNode * c : this->children()) { if (c->type() == EvaluationNode::Type::Complex) { matrix.addChildAtIndexInPlace(c->complexToExpression(complexFormat), i, i); } else { matrix.addChildAtIndexInPlace(Undefined(), i, i); } i++; } matrix.setDimensions(numberOfRows(), numberOfColumns()); return matrix; } template std::complex MatrixComplexNode::trace() const { if (numberOfRows() != numberOfColumns() || numberOfRows() == 0) { return std::complex(NAN, NAN); } int dim = numberOfRows(); std::complex c = std::complex(0); for (int i = 0; i < dim; i++) { c += complexAtIndex(i*dim+i); if (std::isnan(c.real()) || std::isnan(c.imag())) { return std::complex(NAN, NAN); } } return c; } template std::complex MatrixComplexNode::determinant() const { if (numberOfRows() != numberOfColumns() || numberOfChildren() == 0 || numberOfChildren() > Matrix::k_maxNumberOfCoefficients) { return std::complex(NAN, NAN); } std::complex operandsCopy[Matrix::k_maxNumberOfCoefficients]; for (int i = 0; i < numberOfChildren(); i++) { operandsCopy[i] = complexAtIndex(i); // Returns complex(NAN, NAN) if Node type is not Complex } std::complex determinant = std::complex(1); Matrix::ArrayRowCanonize(operandsCopy, m_numberOfRows, m_numberOfColumns, &determinant); return determinant; } template MatrixComplex MatrixComplexNode::inverse() const { if (numberOfRows() != numberOfColumns() || numberOfChildren() == 0 || numberOfChildren() > Matrix::k_maxNumberOfCoefficients) { return MatrixComplex::Undefined(); } std::complex operandsCopy[Matrix::k_maxNumberOfCoefficients]; int i = 0; for (EvaluationNode * c : this->children()) { if (c->type() != EvaluationNode::Type::Complex) { return MatrixComplex::Undefined(); } operandsCopy[i] = complexAtIndex(i); i++; } int result = Matrix::ArrayInverse(operandsCopy, m_numberOfRows, m_numberOfColumns); if (result == 0) { /* Intentionally swapping dimensions for inverse, although it doesn't make a * difference because it is square. */ return MatrixComplex(operandsCopy, m_numberOfColumns, m_numberOfRows); } return MatrixComplex::Undefined(); } template MatrixComplex MatrixComplexNode::transpose() const { // Intentionally swapping dimensions for transpose MatrixComplex result; for (int j = 0; j < numberOfColumns(); j++) { for (int i = 0; i < numberOfRows(); i++) { result.addChildAtIndexInPlace(Complex(complexAtIndex(i*numberOfColumns()+j)), result.numberOfChildren(), result.numberOfChildren()); } } result.setDimensions(numberOfColumns(), numberOfRows()); return result; } // MATRIX COMPLEX REFERENCE template MatrixComplex::MatrixComplex(std::complex * operands, int numberOfRows, int numberOfColumns) : MatrixComplex() { for (int i=0; i(operands[i]), i, i); } setDimensions(numberOfRows, numberOfColumns); } template MatrixComplex::MatrixComplex() : Evaluation(TreePool::sharedPool()->createTreeNode >()) {} template MatrixComplex MatrixComplex::Undefined() { std::complex undef = std::complex(NAN, NAN); return MatrixComplex((std::complex *)&undef, 1, 1); } template MatrixComplex MatrixComplex::createIdentity(int dim) { MatrixComplex result; for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { Complex c = i == j ? Complex(1.0) : Complex(0.0); result.addChildAtIndexInPlace(c, i*dim+j, i*dim+j); } } result.setDimensions(dim, dim); return result; } template void MatrixComplex::setDimensions(int rows, int columns) { setNumberOfRows(rows); setNumberOfColumns(columns); } template void MatrixComplex::addChildAtIndexInPlace(Evaluation t, int index, int currentNumberOfChildren) { if (t.type() != EvaluationNode::Type::Complex) { t = Complex::Undefined(); } Evaluation::addChildAtIndexInPlace(t, index, currentNumberOfChildren); } template class MatrixComplexNode; template class MatrixComplexNode; template class MatrixComplex; template class MatrixComplex; }