# -*- coding: iso-8859-1 -*-
from __future__ import division # 1/2 == .5 (par defaut, 1/2 == 0)

import re

from customtest import *
from mathlib import traduire_formule
from mathlib.custom_objects import Interprete

VERBOSE = False

class TestMathlibCustomObjects(CustomTest):

    def assert_resultat(self, s, resultat, latex = None, **parametres):
        i = Interprete(verbose = VERBOSE, **parametres)
        r, l = i.evaluer(s)
        if r != resultat:
            i = Interprete(verbose = True, **parametres)
            r, l = i.evaluer(s)
            print "ERREUR (" + s + "): ", r, " != ",  resultat
        self.assert_(r == resultat)
        if latex is not None:
            latex = "$" + latex + "$"
            if l != latex:
                print "ERREUR (" + s + "): ", l, " != ",  latex
            self.assert_(l == latex)

    def assert_resoudre(self, s, *args, **kw):
        self.assert_resultat("resoudre(" + s + ")", *args, **kw)

    def assert_approche(self, s, resultat, latex = None, **parametres):
        self.assert_resultat(s, resultat, latex, calcul_exact = False, **parametres)

    def assertEqual(self, x, y):
        if x != y:
            print "ERREUR:", repr(x), "!=", repr(y)
        self.assert_(x == y)

    def assertDernier(self, i, s):
        self.assertEqual(str(i.derniers_resultats[-1]), s)

    def test_exemples_de_base(self):
        # Nombres
        self.assert_resultat('2+2', '4', '4')
        # Symboles
        self.assert_resultat('pi+1+2pi', '1 + 3 pi', '1 + 3 \\pi')
        self.assert_resultat('oo+5*oo', '+oo')
        self.assert_resultat('i**2-i', '-1 - i', '-1 - \\mathrm{i}')
        self.assert_resultat('5e-3', '-3 + 5 e', '-3 + 5 \\mathrm{e}')
        # Analyse
        self.assert_resultat('limite(x^2-x+3,+oo)', '+oo', '+\\infty')
        self.assert_resultat('derive(x^2+2x-3)', '2 + 2 x', '2 + 2 x')
        self.assert_resultat('integre(2x+7)', '7 x + x^2', '7 x + x^{2}')
        self.assert_resultat('integre(x+1,(x,-1,1))', '2', '2')
        self.assert_resultat('integre(x+1,x,-1,1)', '2', '2')
        self.assert_resultat('taylor(sin x,x,0,4)', 'x - x^3/6 + O(x^4)', \
                                        'x - \\frac{1}{6} x^{3} + \\mathcal{O}\\left(x^{4}\\right)')
        self.assert_resultat('cos x>>taylor', \
                                        '1 - x^2/2 + x^4/24 + O(x^5)', \
                                        '1 - \\frac{1}{2} x^{2} + \\frac{1}{24} x^{4} + \\mathcal{O}\\left(x^{5}\\right)')
        # Algèbre
        self.assert_resultat('developpe((x-3)(x+7)(2y+x+5))', \
                                        '-105 - x - 42 y + 8 x y + 9 x^2 + 2 y x^2 + x^3', \
                                        '-105 - x - 42 y + 8 x y + 9 x^{2} + 2 y x^{2} + x^{3}')
        self.assert_resultat('factorise(x^2-7x+3)', \
                                        '(7/2 - x + sqrt(37)/2)(7/2 - x - sqrt(37)/2)',
                                        '\\left(\\frac{7}{2} - x + \\frac{1}{2} \\sqrt{37}\\right) \\left(\\frac{7}{2} - x - \\frac{1}{2} \\sqrt{37}\\right)')
        self.assert_resultat('factorise(x^2+x)', 'x(1 + x)',  'x \\left(1 + x\\right)')
        self.assert_resultat('factor(exp(x)x^2+5/2x*exp(x)+exp(x))', '(1/2 + x)(2 + x)exp(x)')
        self.assert_resultat('factor(exp(x)x^2+2.5x*exp(x)+exp(x))', '(0.5 + x)(2 + x)exp(x)')
        self.assert_resultat('factorise(exp(2x)*x^2+x*exp(x))', \
                                        'x(1 + x exp(x))exp(x)',  \
                                        'x \\left(1 + x \\mathrm{e}^{x}\\right) \\mathrm{e}^{x}')
        self.assert_resultat('factorise(x^2+7x+53)', '53 + 7 x + x^2', '53 + 7 x + x^{2}')
        self.assert_resultat('factor(exp(x)x^2+2x*exp(x)+exp(x))', \
                                        '(1 + x)^2 exp(x)', \
                                        '\left(1 + x\\right)^{2} \\mathrm{e}^{x}')
        self.assert_resultat('cfactorise(x^2+7x+53)', \
                                        '(7/2 + x + i sqrt(163)/2)(7/2 + x - i sqrt(163)/2)', \
                                        '\\left(\\frac{7}{2} + x + \\frac{1}{2} \\mathrm{i} \\sqrt{163}\\right) \\left(\\frac{7}{2} + x - \\frac{1}{2} \\mathrm{i} \\sqrt{163}\\right)')
        self.assert_resultat('evalue(pi-1)', '2.14159265358979324', '2.14159265358979324')
        self.assert_resultat('somme(x^2,(x,1,7))', '140', '140')
        self.assert_resultat('somme(x^2,x,1,7)', '140', '140')
        self.assert_resultat('product(x^2,(x,1,7))', '25401600', '25401600')
        self.assert_resultat('product(x^2,x,1,7)', '25401600', '25401600')
        self.assert_resultat('limit(x^2-x,oo)', '+oo', '+\infty')
        self.assert_resultat('abs(pi-5)', '5 - pi', r'5 - \pi')
        self.assert_resultat('abs(x-5)', 'abs(5 - x)', r'\left|{5 - x}\right|')
        self.assert_resultat('i(1+i)', r'-1 + i',  r'-1 + \mathrm{i}')
        self.assert_resultat('i sqrt(3)', r'i sqrt(3)',  r'\mathrm{i} \sqrt{3}')
        self.assert_resultat('pi sqrt(3)', r'pi sqrt(3)',  r'\pi \sqrt{3}')
        self.assert_resultat('sqrt(1+e)', r'sqrt(1 + e)',  r'\sqrt{1 + \mathrm{e}}')
        self.assert_resultat('(5-2i)(5+2i)', r'29',  r'29')
        self.assert_resultat('resous(2x=1)', r'{1/2}',  r'\{\frac{1}{2}\}')
        self.assert_resultat('jhms(250000)', r'2 j 21 h 26 min 40 s',  r'2 \mathrm{j}\, 21 \mathrm{h}\, 26 \mathrm{min}\, 40 \mathrm{s}')
        self.assert_resultat(r'pi\approx', r'3.14159265358979324',  r'3.14159265358979324', formatage_LaTeX = True)
        self.assert_resultat('rassemble(1/x+1/(x*(x+1)))', '(2 + x)/(x + x^2)', r'\frac{2 + x}{x + x^{2}}')
        self.assert_resultat('factorise(-2 exp(-x) - (3 - 2 x)exp(-x))', '-(5 - 2 x)exp(-x)', r'- \left(5 - 2 x\right) \mathrm{e}^{- x}')

#        self.assert_resultat('resoudre(2+\i=\dfrac{2\i z}{z-1})', '3/5 + 4*i/5', r'\frac{3}{5} + \frac{4}{5} \mathrm{i}')

    def test_fonctions_avances(self):

    def test_resoudre(self):
        self.assert_resoudre('2x+3>5x-4 et 3x+1>=4x-4', r']-oo;7/3[')
        self.assert_resoudre('2=-a+b et -1=3a+b', r'{a: -3/4, b: 5/4}')
        self.assert_resoudre(r'3-x\ge 1+2x\\\text{et}\\4x<2+10x', ']-1/3;2/3]',
                            r']- \frac{1}{3};\frac{2}{3}]',  formatage_LaTeX = True)
        self.assert_resoudre('2exp(x)>3', ']ln(3/2);+oo[')
        self.assert_resoudre('x^3-30x^2+112=0', '{14 - 6 sqrt(7) ; 2 ; 14 + 6 sqrt(7)}', r'\{14 - 6 \sqrt{7}\,;\, 2\,;\, 14 + 6 \sqrt{7}\}')
        # NB: Test très long (15-20 secondes) !
        self.assert_resoudre(r'ln(x^2)-ln(x+1)>1', ']-1;e/2 - sqrt(4 e + exp(2))/2[U]e/2 + sqrt(4 e + exp(2))/2;+oo[')

    def test_approches(self):
        self.assert_approche('pi-1', '2.14159265358979324', '2.14159265358979324')
        self.assert_approche('factor(x^2+2.5x+1)', '(0.5 + x)(2 + x)')
        self.assert_approche('factor(exp(x)x^2+2.5x*exp(x)+exp(x))', '(0.5 + x)(2 + x)exp(x)')
        self.assert_approche('ln(2.5)', '0.916290731874155065')
        self.assert_approche('resoudre(x^3-30x^2+112=0)', '{-1.87450786638754354 ; 2 ; 29.8745078663875435}', r'\{-1.87450786638754354\,;\, 2\,;\, 29.8745078663875435\}')


    def test_session(self):
        i = Interprete(verbose = VERBOSE)
        i.evaluer("1+7")
        i.evaluer("x-3")
        i.evaluer("ans()+ans(1)")
        self.assertDernier(i, "5 + x")
        i.evaluer("f(x, y, z)=2x+3y-z")
        i.evaluer("f(-1, 5, a)")
        self.assertDernier(i, "13 - a")
        i.evaluer("f(x)=x^2-7x+3")
        i.evaluer("f'(x)")
        self.assertDernier(i, "-7 + 2*x")
        # Noms réservés
        self.assertRaises(NameError, i.evaluer, "e=3")
        self.assertRaises(NameError, i.evaluer, "pi=3")
        self.assertRaises(NameError, i.evaluer, "i=3")
        self.assertRaises(NameError, i.evaluer, "oo=3")
        self.assertRaises(NameError, i.evaluer, "factorise=3")
        i.evaluer('f(x)=x+3')
        i.evaluer('[f(j) for j in range(1,11)]')
        self.assertDernier(i, '[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]')
        # Etc.

if __name__ == '__main__':
    unittest.main()
