extern "C" { #include #include #include } #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Poincare { template T Complex::toScalar() const { if (this->imag() == 0.0) { return this->real(); } return NAN; } template static Expression * CreateDecimal(T f) { if (std::isnan(f) || std::isinf(f)) { return new Undefined(); } return new Decimal(f); } template Expression * Complex::complexToExpression(Expression::ComplexFormat complexFormat) const { if (std::isnan(this->real()) || std::isnan(this->imag()) || std::isinf(this->real()) || std::isinf(this->imag())) { return new Poincare::Undefined(); } switch (complexFormat) { case Expression::ComplexFormat::Cartesian: { Expression * real = nullptr; Expression * imag = nullptr; if (this->real() != 0 || this->imag() == 0) { real = CreateDecimal(this->real()); } if (this->imag() != 0) { if (this->imag() == 1.0 || this->imag() == -1) { imag = new Symbol(Ion::Charset::IComplex); } else if (this->imag() > 0) { imag = new Multiplication(CreateDecimal(this->imag()), new Symbol(Ion::Charset::IComplex), false); } else { imag = new Multiplication(CreateDecimal(-this->imag()), new Symbol(Ion::Charset::IComplex), false); } } if (imag == nullptr) { return real; } else if (real == nullptr) { if (this->imag() > 0) { return imag; } else { return new Opposite(imag, false); } return imag; } else if (this->imag() > 0) { return new Addition(real, imag, false); } else { return new Subtraction(real, imag, false); } } default: { assert(complexFormat == Expression::ComplexFormat::Polar); Expression * norm = nullptr; Expression * exp = nullptr; T r = std::abs(*this); T th = std::arg(*this); if (r != 1 || th == 0) { norm = CreateDecimal(r); } if (r != 0 && th != 0) { Expression * arg = nullptr; if (th == 1.0) { arg = new Symbol(Ion::Charset::IComplex); } else if (th == -1.0) { arg = new Opposite(new Symbol(Ion::Charset::IComplex), false); } else if (th > 0) { arg = new Multiplication(CreateDecimal(th), new Symbol(Ion::Charset::IComplex), false); } else { arg = new Opposite(new Multiplication(CreateDecimal(-th), new Symbol(Ion::Charset::IComplex), false), false); } exp = new Power(new Symbol(Ion::Charset::Exponential), arg, false); } if (exp == nullptr) { return norm; } else if (norm == nullptr) { return exp; } else { return new Multiplication(norm, exp, false); } } } } template Complex * Complex::createInverse() const { return new Complex(Division::compute(std::complex(1.0), *this)); } template MatrixComplex::MatrixComplex(std::complex * operands, int numberOfRows, int numberOfColumns) : m_numberOfRows(numberOfRows), m_numberOfColumns(numberOfColumns) { m_operands = new std::complex [numberOfRows*numberOfColumns]; for (int i=0; i MatrixComplex::~MatrixComplex() { if (m_operands != nullptr) { delete [] m_operands; } } template MatrixComplex::MatrixComplex(MatrixComplex&& other) { // Pilfer other's data m_operands = other.m_operands; m_numberOfRows = other.m_numberOfRows; m_numberOfColumns = other.m_numberOfColumns; // Reset other other.m_operands = nullptr; other.m_numberOfRows = 0; other.m_numberOfColumns = 0; } template MatrixComplex::MatrixComplex(const MatrixComplex& other) { // Copy other's data m_numberOfRows = other.m_numberOfRows; m_numberOfColumns = other.m_numberOfColumns; std::complex * operands = new std::complex [m_numberOfRows*m_numberOfColumns]; for (int i=0; i MatrixComplex& MatrixComplex::operator=(MatrixComplex && other) { if (this != &other) { if (m_operands) { delete [] m_operands; } // Pilfer other's ivars m_operands = other.m_operands; m_numberOfRows = other.m_numberOfRows; m_numberOfColumns = other.m_numberOfColumns; // Reset other other.m_operands = nullptr; other.m_numberOfRows = 0; other.m_numberOfColumns = 0; } return *this; } template Expression * MatrixComplex::complexToExpression(Expression::ComplexFormat complexFormat) const { Expression ** operands = new Expression * [numberOfComplexOperands()]; for (int i = 0; i < numberOfComplexOperands(); i++) { operands[i] = Complex(complexOperand(i)).complexToExpression(complexFormat); } Expression * result = new Matrix(operands, numberOfRows(), numberOfColumns(), false); delete[] operands; return result; } template std::complex MatrixComplex::createTrace() const { if (numberOfRows() != numberOfColumns()) { return std::complex(NAN, NAN); } int dim = numberOfRows(); std::complex c = std::complex(0); for (int i = 0; i < dim; i++) { c += complexOperand(i*dim+i); } return c; } template std::complex MatrixComplex::createDeterminant() const { if (numberOfRows() != numberOfColumns()) { return std::complex(NAN, NAN); } std::complex * operandsCopy = new std::complex [m_numberOfRows*m_numberOfColumns]; for (int i=0; i determinant = std::complex(1); Matrix::ArrayRowCanonize(operandsCopy, m_numberOfRows, m_numberOfColumns, &determinant); delete[] operandsCopy; return determinant; } template MatrixComplex * MatrixComplex::createInverse() const { std::complex * operandsCopy = new std::complex [m_numberOfRows*m_numberOfColumns]; for (int i=0; i * inverse = nullptr; if (result == 0) { // Intentionally swapping dimensions for inverse, although it doesn't make a difference because it is square inverse = new MatrixComplex(operandsCopy, m_numberOfColumns, m_numberOfRows); } delete [] operandsCopy; return inverse; } template MatrixComplex * MatrixComplex::createTranspose() const { std::complex * operands = new std::complex [numberOfComplexOperands()]; for (int i = 0; i < numberOfRows(); i++) { for (int j = 0; j < numberOfColumns(); j++) { operands[j*numberOfRows()+i] = complexOperand(i*numberOfColumns()+j); } } // Intentionally swapping dimensions for transpose MatrixComplex * matrix = new MatrixComplex(operands, numberOfColumns(), numberOfRows()); delete[] operands; return matrix; } template MatrixComplex MatrixComplex::createIdentity(int dim) { std::complex * operands = new std::complex [dim*dim]; for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { if (i == j) { operands[i*dim+j] = std::complex(1); } else { operands[i*dim+j] = std::complex(0); } } } MatrixComplex matrix = MatrixComplex(operands, dim, dim); delete [] operands; return matrix; } template class Complex; template class Complex; template class MatrixComplex; template class MatrixComplex; }