/* Rsolution d'quations */
rsoudre(_expression) ->
	rsoudre(_expression , x , _r) ,
	writeln('x = ' , _r).

rsoudre(_exp=_n , _x , _d) ->
	simplif(_exp-_n , _s) ,
	rsoudre(_s , _x , _d).

		/* l'quation est un produit = 0 */
rsoudre(_exp1*_exp2 , _x , _d) -> / ,
	rsoudre_fact(_exp1*_exp2 , _x , _d) .

		/* l'quation ne contient x qu'une seule fois */
rsoudre(_exp , _x , _d) ->
	compte(_exp , _x , 1 ) , / ,
	rsoudre_isole(_exp=0 , _x , _d) .

		/* l'quation est un polynome en x */
rsoudre(_exp , _x , _d) ->
	is_polynome(_exp , _x) , / ,
	en_forme_normale(_exp , _x , _exp2) ,
	rsoudre_poly(_exp2 , _x , _d) .

		/* on va changer de variable */
rsoudre(_exp , _x , _d) ->
	rsoudre_substitution(_exp , _x , _d) , / .

		/* l'quation est un produit = 0 */
rsoudre_fact(_a * _b , _x , _r) -> rsoudre(_a , _x , _r).
rsoudre_fact(_a * _b , _x , _r) -> rsoudre(_b , _x , _r).

		/* l'quation ne contient x qu'une seule fois */
rsoudre_isole(_t=_d , _t , _d) -> / .
rsoudre_isole(_p(_x)=_z , _t , _d) ->
	inverse(_p(_) , _invp(_)) ,
	simplif(_invp(_z) , _q) ,
	rsoudre_isole(_x=_q , _t , _d).
rsoudre_isole(_p(_x , _y)=_z , _t , _d) ->
	compte(_y , _t , 0) , / ,
	inverse(1 , _p(_z,_y) , _r) ,
	simplif(_r , _m) ,
	rsoudre_isole(_x=_m , _t , _d).
rsoudre_isole(_p(_x , _y)=_z , _t , _d) ->
	compte(_x , _t , 0) ,
	inverse(2 , _p(_z,_x) , _r) ,
	simplif(_r , _m) ,
	rsoudre_isole(_y=_m , _t , _d).

		/* l'quation est un polynome en x */
rsoudre_poly([f(_a,1) , f(_b,0) ], _x , _d) -> / ,
	simplif(-_b , _e) ,
	simplif(_e/_a , _d) .

rsoudre_poly([ f(_a,2) , f(_b,1) , f(_c,0) ] , _x , _d) ->
	simplifie(_b*_b-4*_a*_c , _delta) ,
	poly_2(_a , _b , _c , _d , _delta) .

rsoudre_poly([f(_a,4) , f(0,3) , f(_b,2) , f(0,1) , f(_c,0)] , _x , _d) ->
	_c /= 0 ,
	simplifie(_b*_b-4*_a*_c , _delta) ,
	poly_2(_a , _b , _c , _f , _delta) ,
	rsoudre(_x^2-_f , _x , _d) .

xrsoudre_poly([f(_a,3) , f(_b,2) , f(_c,1) , f(_d,0)] , _x , _r) ->
	_d /= 0 ,
	simplifie((3*_a*_c-b^2)/(9*a^2) , _p) ,
	simplifie( (2*_b^3/27*_a^2-_b*_c/(3*_a^2)+_d/_a)/2 , _q) ,
	simplifie(_p^3 +_q^2 , _delta) ,
	poly_3(_p , _q , _f , _delta) ,
	rsoudre(_x+_b/3*_a = _f) .

rsoudre_poly(_fn , _x , 0) ->
	x_in_all(_fn ) .
rsoudre_poly(_fn , _x , _r) ->
	x_in_all(_fn ) , / ,
	decx_in_all(_fn , _q) ,
	rsoudre_poly(_q , _x , _r) .

x_in_all([f(0 , 0)]) -> / .
x_in_all([f(_k,_d) , !_suite]) ->
	x_in_all(_suite).

decx_in_all( [f(0,0)] , []) -> / .
decx_in_all([ f(0 , _n) , !_suite] , [f(0,_n) ,!_q]) -> / ,
	decx_in_all(_suite , _q).
decx_in_all([ f(_k , _n) , !_suite] , [f(_k,_m) , !_q]) ->
	simplif(_n-1 , _m) ,
	decx_in_all(_suite , _q).


poly_2(_a , _b , _c , _d , _delta) ->
	number(_delta) ,
	_delta < 0 , / , fail.
poly_2(_a , _b , _c , _d , _delta) ->
	simplifie((-_b+_delta^0.5)/(2*_a) , _d) .
poly_2(_a , _b , _c , _d , _delta) ->
	simplifie((-_b-_delta^0.5)/(2*_a) , _d) .

poly_3(_p , _q , _f , _delta) ->
	_delta > 0 ,
	simplifie( (-_q+(_delta)^0.5)^1/3
			+ (-_q-(_delta)^0.5)^1/3 , _f) .
poly_3(_p , _q , _f , _delta) ->
	_delta < 0 .

compte(_x , _x , 1 ) -> / .
compte(_y , _x , 0) -> const(_y) , / .
compte(_p(_a , _b) , _x , _n) ->
	compte(_a , _x , _n1) ,

	compte(_b , _x , _n2) ,
	_n :== _n1 + _n2 .
compte(_p(_a) , _x , _n) ->
	compte(_a , _x , _n) .

hsh_coded(inverse(_,_)).
inverse(-(_x) , -(_x)) -> / .
inverse(sin(_x) , arcsin(_x)) -> / .
inverse(cos(_x) , arccos(_x)) -> / .
inverse(tg(_x) , arctg(_x)) -> / .
inverse(cotg(_x) , arccotg(_x)) -> / .
inverse(ln(_x) , exp(_x)) -> / .

inverse(1,_a+_b , _a-_b) -> / .
inverse(2,_a+_b , _a-_b) -> / .
inverse(1,_a-_b , _a+_b) -> / .
inverse(2,_a-_b , _b-_a) -> / .
inverse(1,_a*_b , _a/_b) -> / .
inverse(2,_a*_b , _a/_b) -> / .
inverse(1,_a/_b , _a*_b) -> / .
inverse(2,_a/_b , _b/_a) -> / .
inverse(1,_a^_b , _a^_n) -> simplif(1/_b , _n) .
inverse(1,_a^_b , _dd) ->
	_b :== trunc(_b) ,
	mod(_b,2)==0 ,
	simplif(1/_b , _n) ,
	simplif(_a^_n , _d) ,
	moins(_d , _dd) , / .

		/* on va changer de variable */
rsoudre_substitution(_exp , _x , _d) ->
	substitution(_exp , _x , _newx ) ,
	substitue(_exp , _x , _newx , _newexp) ,
	rsoudre(_newexp , _x , _d1) ,
	rsoudre(_newx-_d1 , _x , _d).

substitution(_exp , _x , _newx , _newexp) ->
	liste_gros(_exp , _x , _gros) ,
	substituant(_x , _gros , _newx) ,
	substitue(_exp , _x , _newx , _newexp).