#include #include #include extern "C" { #include } namespace Poincare { template Expression * ApproximationEngine::map(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexCompute compute) { assert(expression->numberOfOperands() == 1); Expression * input = expression->operand(0)->approximate(context, angleUnit); Expression * result = nullptr; if (input->type() == Expression::Type::Complex) { Complex * c = static_cast *>(input); result = new Complex(compute(*c, angleUnit)); } else { assert(input->type() == Expression::Type::Matrix); Expression ** operands = new Expression * [input->numberOfOperands()]; for (int i = 0; i < input->numberOfOperands(); i++) { assert(input->operand(i)->type() == Expression::Type::Complex); const Complex * c = static_cast *>(input->operand(i)); operands[i] = new Complex(compute(*c, angleUnit)); } result = new Matrix(operands, static_cast(input)->numberOfRows(), static_cast(input)->numberOfColumns(), false); delete[] operands; } delete input; return result; } template Expression * ApproximationEngine::mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes, ComplexAndMatrixReduction computeOnComplexAndMatrix, MatrixAndComplexReduction computeOnMatrixAndComplex, MatrixAndMatrixReduction computeOnMatrices) { Expression * result = expression->operand(0)->approximate(context, angleUnit); for (int i = 1; i < expression->numberOfOperands(); i++) { Expression * intermediateResult = nullptr; Expression * nextOperandEvaluation = expression->operand(i)->approximate(context, angleUnit); if (result->type() == Expression::Type::Complex && nextOperandEvaluation->type() == Expression::Type::Complex) { const Complex * c = static_cast *>(result); const Complex * d = static_cast *>(nextOperandEvaluation); intermediateResult = new Complex(computeOnComplexes(*c, *d)); } else if (result->type() == Expression::Type::Complex) { const Complex * c = static_cast *>(result); assert(nextOperandEvaluation->type() == Expression::Type::Matrix); const Matrix * n = static_cast(nextOperandEvaluation); intermediateResult = computeOnComplexAndMatrix(c, n); } else if (nextOperandEvaluation->type() == Expression::Type::Complex) { assert(result->type() == Expression::Type::Matrix); const Matrix * m = static_cast(result); const Complex * d = static_cast *>(nextOperandEvaluation); intermediateResult = computeOnMatrixAndComplex(m, d); } else { assert(result->type() == Expression::Type::Matrix); const Matrix * m = static_cast(result); assert(nextOperandEvaluation->type() == Expression::Type::Matrix); const Matrix * n = static_cast(nextOperandEvaluation); intermediateResult = computeOnMatrices(m, n); } delete result; delete nextOperandEvaluation; result = intermediateResult; if (result == nullptr) { return new Complex(Complex::Float(NAN)); } } return result; } template Matrix * ApproximationEngine::elementWiseOnComplexAndComplexMatrix(const Complex * c, const Matrix * m, ComplexAndComplexReduction computeOnComplexes) { Expression ** operands = new Expression * [m->numberOfRows()*m->numberOfColumns()]; for (int i = 0; i < m->numberOfOperands(); i++) { const Complex * d = static_cast *>(m->operand(i)); operands[i] = new Complex(computeOnComplexes(*d, *c)); } Matrix * result = new Matrix(operands, m->numberOfRows(), m->numberOfColumns(), false); delete[] operands; return result; } template Matrix * ApproximationEngine::elementWiseOnComplexMatrices(const Matrix * m, const Matrix * n, ComplexAndComplexReduction computeOnComplexes) { if (m->numberOfRows() != n->numberOfRows() || m->numberOfColumns() != n->numberOfColumns()) { return nullptr; } Expression ** operands = new Expression * [m->numberOfRows()*m->numberOfColumns()]; for (int i = 0; i < m->numberOfOperands(); i++) { const Complex * c = static_cast *>(m->operand(i)); const Complex * d = static_cast *>(n->operand(i)); operands[i] = new Complex(computeOnComplexes(*c, *d)); } Matrix * result = new Matrix(operands, m->numberOfRows(), m->numberOfColumns(), false); delete[] operands; return result; } template Poincare::Expression * Poincare::ApproximationEngine::map(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexCompute compute); template Poincare::Expression * Poincare::ApproximationEngine::map(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexCompute compute); template Poincare::Expression * Poincare::ApproximationEngine::mapReduce(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexAndComplexReduction computeOnComplexes, Poincare::ApproximationEngine::ComplexAndMatrixReduction computeOnComplexAndMatrix, Poincare::ApproximationEngine::MatrixAndComplexReduction computeOnMatrixAndComplex, Poincare::ApproximationEngine::MatrixAndMatrixReduction computeOnMatrices); template Poincare::Expression * Poincare::ApproximationEngine::mapReduce(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexAndComplexReduction computeOnComplexes, Poincare::ApproximationEngine::ComplexAndMatrixReduction computeOnComplexAndMatrix, Poincare::ApproximationEngine::MatrixAndComplexReduction computeOnMatrixAndComplex, Poincare::ApproximationEngine::MatrixAndMatrixReduction computeOnMatrices); template Poincare::Matrix * Poincare::ApproximationEngine::elementWiseOnComplexAndComplexMatrix(Poincare::Complex const*, const Poincare::Matrix *, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); template Poincare::Matrix* Poincare::ApproximationEngine::elementWiseOnComplexAndComplexMatrix(Poincare::Complex const*, const Poincare::Matrix*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); template Poincare::Matrix* Poincare::ApproximationEngine::elementWiseOnComplexMatrices(const Poincare::Matrix*, const Poincare::Matrix*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); template Poincare::Matrix* Poincare::ApproximationEngine::elementWiseOnComplexMatrices(const Poincare::Matrix*, const Poincare::Matrix*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); }