#include #include #include #include extern "C" { #include } namespace Poincare { template T absMod(T a, T b) { T result = std::fmod(std::fabs(a), b); return result > b/2 ? b-result : result; } template std::complex ApproximationEngine::truncateRealOrImaginaryPartAccordingToArgument(std::complex c) { T arg = std::arg(c); T precision = 10*Expression::epsilon(); if (absMod(arg, (T)M_PI) <= precision) { c.imag(0); } if (absMod(arg-(T)M_PI/2.0, (T)M_PI) <= precision) { c.real(0); } return c; } template Evaluation * ApproximationEngine::map(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexCompute compute) { assert(expression->numberOfOperands() == 1); Evaluation * input = expression->operand(0)->privateApproximate(T(), context, angleUnit); Evaluation * result = nullptr; if (input->type() == Evaluation::Type::Complex) { Complex * c = static_cast *>(input); result = new Complex(compute(*c, angleUnit)); } else { assert(input->type() == Evaluation::Type::MatrixComplex); MatrixComplex * m = static_cast *>(input); std::complex * operands = new std::complex [m->numberOfComplexOperands()]; for (int i = 0; i < m->numberOfComplexOperands(); i++) { const std::complex c = m->complexOperand(i); operands[i] = compute(c, angleUnit); } result = new MatrixComplex(operands, m->numberOfRows(), m->numberOfColumns()); delete[] operands; } delete input; return result; } template Evaluation * ApproximationEngine::mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes, ComplexAndMatrixReduction computeOnComplexAndMatrix, MatrixAndComplexReduction computeOnMatrixAndComplex, MatrixAndMatrixReduction computeOnMatrices) { Evaluation * result = expression->operand(0)->privateApproximate(T(), context, angleUnit); for (int i = 1; i < expression->numberOfOperands(); i++) { Evaluation * intermediateResult = nullptr; Evaluation * nextOperandEvaluation = expression->operand(i)->privateApproximate(T(), context, angleUnit); if (result->type() == Evaluation::Type::Complex && nextOperandEvaluation->type() == Evaluation::Type::Complex) { const Complex * c = static_cast *>(result); const Complex * d = static_cast *>(nextOperandEvaluation); intermediateResult = new Complex(computeOnComplexes(*c, *d)); } else if (result->type() == Evaluation::Type::Complex) { const Complex * c = static_cast *>(result); assert(nextOperandEvaluation->type() == Evaluation::Type::MatrixComplex); const MatrixComplex * n = static_cast *>(nextOperandEvaluation); intermediateResult = new MatrixComplex(computeOnComplexAndMatrix(*c, *n)); } else if (nextOperandEvaluation->type() == Evaluation::Type::Complex) { assert(result->type() == Evaluation::Type::MatrixComplex); const MatrixComplex * m = static_cast *>(result); const Complex * d = static_cast *>(nextOperandEvaluation); intermediateResult = new MatrixComplex(computeOnMatrixAndComplex(*m, *d)); } else { assert(result->type() == Evaluation::Type::MatrixComplex); const MatrixComplex * m = static_cast *>(result); assert(nextOperandEvaluation->type() == Evaluation::Type::MatrixComplex); const MatrixComplex * n = static_cast *>(nextOperandEvaluation); intermediateResult = new MatrixComplex(computeOnMatrices(*m, *n)); } delete result; delete nextOperandEvaluation; result = intermediateResult; assert(result != nullptr); if (result->isUndefined()) { delete result; return new Complex(Complex::Undefined()); } } return result; } template MatrixComplex ApproximationEngine::elementWiseOnMatrixComplexAndComplex(const MatrixComplex m, const std::complex c, ComplexAndComplexReduction computeOnComplexes) { std::complex * operands = new std::complex [m.numberOfRows()*m.numberOfColumns()]; for (int i = 0; i < m.numberOfComplexOperands(); i++) { const std::complex d = m.complexOperand(i); operands[i] = computeOnComplexes(d, c); } MatrixComplex result = MatrixComplex(operands, m.numberOfRows(), m.numberOfColumns()); delete[] operands; return result; } template MatrixComplex ApproximationEngine::elementWiseOnComplexMatrices(const MatrixComplex m, const MatrixComplex n, ComplexAndComplexReduction computeOnComplexes) { if (m.numberOfRows() != n.numberOfRows() || m.numberOfColumns() != n.numberOfColumns()) { return MatrixComplex::Undefined(); } std::complex * operands = new std::complex [m.numberOfRows()*m.numberOfColumns()]; for (int i = 0; i < m.numberOfComplexOperands(); i++) { const Complex c = m.complexOperand(i); const Complex d = n.complexOperand(i); operands[i] = computeOnComplexes(c, d); } MatrixComplex result = MatrixComplex(operands, m.numberOfRows(), m.numberOfColumns()); delete[] operands; return result; } template std::complex Poincare::ApproximationEngine::truncateRealOrImaginaryPartAccordingToArgument(std::complex); template std::complex Poincare::ApproximationEngine::truncateRealOrImaginaryPartAccordingToArgument(std::complex); template Poincare::Evaluation * Poincare::ApproximationEngine::map(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexCompute compute); template Poincare::Evaluation * Poincare::ApproximationEngine::map(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexCompute compute); template Poincare::Evaluation * 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::Evaluation * 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::MatrixComplex Poincare::ApproximationEngine::elementWiseOnMatrixComplexAndComplex(const Poincare::MatrixComplex, const std::complex, std::complex (*)(std::complex, std::complex)); template Poincare::MatrixComplex Poincare::ApproximationEngine::elementWiseOnMatrixComplexAndComplex(const Poincare::MatrixComplex, std::complex const, std::complex (*)(std::complex, std::complex)); template Poincare::MatrixComplex Poincare::ApproximationEngine::elementWiseOnComplexMatrices(const Poincare::MatrixComplex, const Poincare::MatrixComplex, std::complex (*)(std::complex, std::complex)); template Poincare::MatrixComplex Poincare::ApproximationEngine::elementWiseOnComplexMatrices(const Poincare::MatrixComplex, const Poincare::MatrixComplex, std::complex (*)(std::complex, std::complex)); }