(* ::Package:: *)

(* Mathematica Package *)

(* Created by the Wolfram Workbench 25 mars 2007 *)
(* F. MELOTTE http://www.macformath.net/ *)

BeginPackage["calculus`",{"math`"}]
(* Exported symbols added here with SymbolName::usage *) 


Periode::usage="periode"


Detaille::usage="wrapper pour resoudre un exercice en affichant les details. exemple= Detaille[Inequation[x<1/x,x]]"
Resoudre::usage="Wrapper pour resoudre un exercice sans detail. Exemple= Resoudre[Inequation[x<1/x,x]]"
Inequation::usage="wrapper pour une inequation reductible au 2nd degre. on peut lui appliquer ensuite la fonction Detaille"



Equalogexp::usage = "recherche les solutions d une equation log ou exponentielle"


Dom::usage = "Dom[f[x],x] determine sous forme logique le domaine de definition d'une fonction algebrique f[x_]"

Gf::usage=" Gf[f,{x,y}] definit l ensemble du plan correspondant au graphe cartesien de f (en-tete= Ens)"

Droites::usage=" ??? "

Adh::usage="determine l adherence"
Int::usage="interieur"

Num::usage="donne une ecriture sous forme de radicaux"

Signedef::usage = "donne le signe de f pour x=a"

TableaudeSignes::usage = "Presente le tableau de signes de f"
TableaudeSignesComplet::usage=""
TableauRecapitulatif::usage = "Presente le tableau recapitulatif de f"
TableaudeSignesD::usage="tableau de signe de la derivee premiere"

Limite::usage="Limite[f,x,a] definit une limite et l affiche sans la calculer"
PlusInfini::usage="PlusInfini[...] remplace Infinity par + infini"

LimiteNotation::usage="LimiteNotation[x,a] affiche le symbole lim"
CalculLimite::usage = "CalculLimite[f,x,a] renvoie les resultats de la limite sous forme codee (utile en interne)"

Presente::usage = "presente l'ensemble, le domaine,..."

DomQ::usage="DomQ[f,x,a] retourne True ou False suivant que a appartient au domaine ou non"
Valeur::usage=""
AdhDomQ::usage="AdhDomQ[f,x,a] retourne True ou False suivant que a adhere au dom f ou non"
ValeursDom::usage="donne la liste des valeurs qui adherent au domaine"


Presentef::usage = "presente la fonction f(x)"

Racines::usage="Racines[f[x],x] calcule les racines de la fonction"
TexteRacines::usage="donne la primitive graphique des abscisses"
InterX::usage="InterX[f,x] recherche l intersection  de Gf avec l axe des x"
InterY::usage="InterX[f,x] recherche l intersection  de Gf avec l axe des y"

Domaine::usage = "Domaine[f[x],x] determine sous forme ensembliste le domaine de definition d'une fonction algebrique f[x_]"
Imagef::usage="Imagef[f,x,y] determine l image de la fonction f"

ListeValeurs::usage="ListeValeurs[f,x] donne la liste des valeurs a mettre dans le tableau"

EtudeCroissance::usage=""
Croissance::usage="Croissance[f[x],x] determine les intervalles de croissance de certaines fonctions"
Decroissance::usage="Decroissance[f[x],x] determine les intervalles de decroissance de certaines fonctions"

Parite::usage="Parite[f[x],x] donne la parite de la fonction (0 = paire, 1=impaire)"

AV::usage = "recherche des asymptotes verticales"
AsymptoteV::usage="donne les primitives graphiques des asymptotes ????????"

Asymptotes::usage="recherche des asymptotes"

AO::usage = "recherche des asymptotes obliques ou horizontales"

AODroite::usage = "recherche des asymptotes obliques ou horizontales a droite"

AOGauche::usage = "recherche des asymptotes obliques ou horizontales a gauche"

Extremums::usage = "recherche des eventuels max et min"

Inflexions::usage = "recherche des eventuels points d inflexion"
InflexionQ::usage="v\.0erifie si en a il y a un point d inflexion"
Derivee::usage = "calcule la derivee de f(x)"
DeriveeSeconde::usage = "calcule la derivee seconde de f(x)"

Tangente::usage=" Tangente[f,x,a] calcule une equation cartesienne de la tge \.08 f au pt d abscisse a"
DetailTangente::usage = "DetailTangente[f,x,a] calcule en detail une equation cartesienne de la tge \.08 f au pt d abscisse a"

EnonceComposee::usage = "ecriture de f o g o h"

Composee::usage = "determine f o g o h"

CalculPrimitives::usage = "calcule l integrale suivante"

EnoncePrimitives::usage = "affiche l enonce de l integrale"
Primitive::usage="calcule une primitive"
Integrale::usage="Integrale affiche sans evaluer une integrale"
EnonceIntegrale::usage="enonce une integrale definie"
Calcule::usage="calcule une integrale definie"


Graphique::usage = "Graphique utilise comme Plot"
Graphef::usage="graphe de la fonction et ses asymptotes"

Etudef::usage = "Etude d une fonction"

Primitivet::usage = "Primitivet [f,x,t,subs] calcule la primitive comme fonction de t utilisant la substitution x = subs"

CalculIntegralet::usage = "CalculIntegralet[f,x,a,b,t,subs] calcule l integrale definie en utilisant la substitution x = subs"

Detail::usage = "Detail[Integrale] donne les details de l integrale" 

Surface::usage="Surface[f,g,x] calcule la surface comprise entre les deux courbes f et g"

Volume::usage="Volume[f,g,x] calcule le volume comprise entre les deux courbes f et g"

Interfg::usage="Interfg[f,g,x] determine les points d intersection entre f et g"
Difference::usage="essaie de determiner si f ou g est au dessus"


Reciproque::usage="Reciproque[f,x,y] recherche l expression algebrique de la relation reciproque de f"

Etude::usage="Etude[1,f] donne le dom, im, lim et racines +graphe"

TableauXY::usage="TableauXY[f,{x,a,b,dx}] donne un tableau X Y"
GrapheXY::usage=""

Exercices::usage="Exercices[l,n] liste les exercices l[i] de i jusque n"
Solutions::usage="Exercices[l,n] liste les solutions des exercices l[i] de i jusque n"
SolutionsenDetail::usage="Exercices[l,n] liste les solutions des exercices l[i] de i jusque n"


Begin["`Private`"]
(* Implementation of the package *)
(* racines cubiques et impaires *)
(*protected = Unprotect[Power]
x_^r_Rational := (-(-x)^(1/Denominator[r]))^Numerator[r] /;Negative[x] && OddQ[Denominator[r]]
Protect[Evaluate[protected]]
*)

Unprotect[Global`y,Global`x,Global`k]
Clear[Global`y,Global`x,Global`k]
Protect[Global`y,Global`x,Global`k]

(*cadre par defaut pour la droite reelle 
cadreens={{-10,10},{0,2/10}}
  ????????????*)

	
(*tentative de racine cubique*)

RacineCubique[x_]:=Piecewise[{{x^(1/3), x >= 0}, {-Abs[x]^(1/3), x < 0}},Indeterminate]
Curt[-1]=-1
Format[Curt[x_]]:=x^(1/3)
Curt[x_]:=(RacineCubique[x])/;NumericQ[x]
Curt /: D[Curt[g_], x_] := D[g^(1/3), x] /. u_^(1/3) -> Curt[u]
(*Curt /: D[Curt[g_], x_] := D[g, x]/(3 Curt[g^2])*)
Curt /: D[Curt[g_], {x_,2}] := -2 D[g, x]/(9 Curt[g^5])


reglesens={Axes->{True,False},AspectRatio -> Automatic,Ticks->math`ticks, GridLines -> math`ticks,GridLinesStyle -> Directive[LightGray, Dotted]}





(*						asymptote verticale		*)

(*
TexteRacines[fct_,x_]:=Block[{f,racs,tablerac,i},
	f=ReleaseHold[fct];
	racs=Extraitvaleurs[Racines[ReleaseHold[f],x]];
	tablerac=Graphics[Table[Text[racs[[i]],{racs[[i]],-0.2}],{i,1,Length[racs]}],Axes->True]
	]
*)

(*    														RESOLUTION D INEQUATIONS		*)
Format[Inequation[ineq_,x_]]:=ineq

Detaille[Inequation[ineq_, x_]] :=  Block[{inequation, membre1, membre2, inegalite},
  inequation = ineq;
  membre1 = inequation[[1]]; membre2 = inequation[[2]];
  inegalite = Head[inequation];
  
  If[membre2 != 0,
   inequation = inegalite[membre1 - membre2, 0];
   Print[inequation], 
   Print[Style["obtenir 0 dans le second membre de l'in\[EAcute]quation", 
     Italic, Darker[Green]]];
   inequation = inegalite[membre1 - membre2, 0];
   Print[inequation],
   Print[Style["obtenir 0 dans le second membre de l'in\[EAcute]quation", 
     Italic, Darker[Green]]];
   inequation = inegalite[membre1 - membre2, 0];
   Print[inequation]
   ];
  membre1 = inequation[[1]]; membre2 = inequation[[2]]; 
  inegalite = Head[inequation];
  If[Head[membre1] == Plus,
   Print[Style["obtenir un produit ou un quotient ", Italic, 
     Darker[Green]]];
   inequation = Together[inegalite[membre1 - membre2, 0]];
   membre1 = inequation[[1]]; membre2 = inequation[[2]]; 
   inegalite = Head[inequation];
   Print[inequation]];
  Print[Style["racine(s) du num\[EAcute]rateur:", Italic, Darker[Green]]];
  Print[Racines[Numerator[membre1], x, 1]];
  If[Denominator[membre1]=!=1,
  	Print[Style["racine(s) du d\[EAcute]nominateur:", Italic, Darker[Green]]];
  	Print[Racines[Denominator[membre1], x, 1]]
  ];
  Print[Style["tableau de signes:", Italic, Darker[Green]]];
  Print[TableaudeSignesComplet[membre1, x,Valeurs->False]];
  Print[Style["solution: ", Italic, Darker[Green]]];
   Print["S = ", math`Ensemble[ineq, x]];
  ]

Resoudre[Inequation[ineq_,x_]]:=Block[{i},
	math`Ensemble[ineq,x]
]
Graphe[Inequation[ineq_,x_]]:=Block[{i},
	math`Graphe[math`Ensemble[ineq,x]]
]






(*											ANALYSE 	ANALYSE			ANALYSE			ANALYSE			ANALYSE			ANALYSE			*)

(* 		adherence 		*)
Adh[True] := True
Adh[math`Ens[True,x_]]:=math`Ens[True,x]
Adh[False, x_] := False
Adh[math`Ens[False,x_]]:=math`Ens[False,x]
Adh[Or[a_, b_], x_] := Or[Adh[a, x], Adh[b, x]]
Adh[math`Ens[Or[a_,b_],x_]] := math`Ens[Or[Adh[a,x], Adh[b,x]],x]
Adh[math`Ens[And[a_,b_],x_]] := math`Ens[And[Adh[a,x], Adh[b,x]],x]
Adh[math`Ens[Unequal[x_, a_],x_]] := math`Ens[Equal[x, a],x]
Adh[math`Ens[Equal[x_, a_], x_]] := math`Ens[Equal[x, a],x]
Adh[math`Ens[Less[x_, a_], x_]] := math`Ens[LessEqual[x, a],x]
Adh[math`Ens[LessEqual[x_, a_], x_]] := math`Ens[LessEqual[x, a],x]
Adh[math`Ens[Greater[x_, a_], x_]] := math`Ens[GreaterEqual[x, a],x]
Adh[math`Ens[GreaterEqual[x_, a_], x_]] := math`Ens[GreaterEqual[x, a],x]
Adh[math`Ens[Inequality[a_, Less, x_, Less, b_], x_]] := math`Ens[Inequality[a,LessEqual, x, LessEqual, b],x]
Adh[math`Ens[Inequality[a_,LessEqual, x_, Less, b_],x_]] := math`Ens[Inequality[a,LessEqual, x, LessEqual, b],x]
Adh[math`Ens[Inequality[a_, Less, x_, LessEqual, b_], x_]] := math`Ens[Inequality[a, LessEqual, x, LessEqual, b],x]
Adh[math`Ens[Inequality[a_, LessEqual, x_, LessEqual, b_], x_]] := math`Ens[Inequality[a,LessEqual, x, LessEqual, b],x]

(* utilise pour l adherence au domaine AdhDomQ*)
Adh[And[a_, b_], x_] := And[Adh[a, x], Adh[b, x]]
Adh[Unequal[x_, a_], x_] := Equal[x, a]
Adh[Equal[x_, a_], x_] := Equal[x, a]
Adh[Reals, x_] := Reals
Adh[Less[x_, a_], x_] := LessEqual[x, a]
Adh[LessEqual[x_, a_], x_] := LessEqual[x, a]
Adh[Greater[x_, a_], x_] := GreaterEqual[x, a]
Adh[GreaterEqual[x_, a_], x_] := GreaterEqual[x, a]
Adh[Inequality[a_, Less, x_, Less, b_], x_] := Inequality[a,LessEqual, x, LessEqual, b]
Adh[Inequality[a_,LessEqual, x_, Less, b_],x_] := Inequality[a, LessEqual, x, LessEqual, b]
Adh[Inequality[a_, Less, x_, LessEqual, b_], x_] := Inequality[a, LessEqual, x, LessEqual, b]
Adh[Inequality[a_, LessEqual, x_, LessEqual, b_], x_] := Inequality[a,LessEqual, x, LessEqual, b]
(*		interieur		*)

Int[True] := True
Int[math`Ens[True,x_]]:=math`Ens[True,x]
Int[False, x_] := False
Int[math`Ens[False,x_]]:=math`Ens[False,x]
Int[Or[a_, b_], x_] := Or[Int[a, x], Int[b, x]]
Int[math`Ens[Or[a_,b_],x_]] := math`Ens[Or[Int[a,x], Int[b,x]],x]
Int[math`Ens[And[a_,b_],x_]] := math`Ens[And[Int[a,x], Int[b,x]],x]
Int[math`Ens[Unequal[x_, a_],x_]] := math`Ens[Unequal[x, a],x]
Int[math`Ens[Equal[x_, a_], x_]] := math`Ens[Unequal[x, a],x]
Int[math`Ens[Less[x_, a_], x_]] := math`Ens[Less[x, a],x]
Int[math`Ens[LessEqual[x_, a_], x_]] := math`Ens[Less[x, a],x]
Int[math`Ens[Greater[x_, a_], x_]] := math`Ens[Greater[x, a],x]
Int[math`Ens[GreaterEqual[x_, a_], x_]] := math`Ens[Greater[x, a],x]
Int[math`Ens[Inequality[a_, Less, x_, Less, b_], x_]] := math`Ens[Inequality[a,Less, x, Less, b],x]
Int[math`Ens[Inequality[a_,LessEqual, x_, Less, b_],x_]] := math`Ens[Inequality[a,Less, x, Less, b],x]
Int[math`Ens[Inequality[a_, Less, x_, LessEqual, b_], x_]] := math`Ens[Inequality[a, Less, x, Less, b],x]
Int[math`Ens[Inequality[a_, LessEqual, x_, LessEqual, b_], x_]] := math`Ens[Inequality[a,Less, x, Less, b],x]

(* a		deplacer !!!!!!*)

(* resolutions d equations exponentielles logarithmiques *)
Equalogexp[equation_, x_] := Block[{e,s},
      e = ReleaseHold[equation] /. math`logToLog;
      s = Reduce[e, x, Reals];
      s = s /. Log[n_Integer]:> SimplifieLog[n];
      math`Ensemble[s, x]
      ]
 
SimplifieLog[explog_]:=Block[{liste,sol,exp,i},
	liste = FactorInteger[explog]; sol = 0;
	Do[exp = liste[[i]];
  	sol = sol + exp[[2]]*Log[exp[[1]]], {i, Length[liste]}];
	sol
	]




(**********TRAITEMENT D UNE FONCTION********)
traitementf[fct_,x_Symbol]:=ReleaseHold[fct]/.{Curt->RacineCubique,math`logToLog}
(*le x comme 2nd argument n a pas de raison d etre.....*)

(* valeur de f en a *)
(*si la valeur n est pas un reel, donne Complex pour un nombre complexe ou Indeterminate pour [0/0] ou ComplexInfinity pour l infini..

Valeur[] retourne \[NotExists] si la fct n existe pas*)


Valeur[fct_,x_Symbol,a_]:=Block[{f,fa},
	f=traitementf[fct,x];
	If[Not[DomQ[f,x,a]],Return["\[NotExists]"]];
	fa=ComplexExpand[(f/.x->a)]/. math`regleracine
	
(*	If[Or[! FreeQ[fa, I, Infinity], !FreeQ[fa, Complex, Infinity],fa===ComplexInfinity], 
		"\[NotExists]", fa, fa
		]
*)
	]/;NumericQ[a]


Valeur[fct_,x_Symbol,DirectedInfinity[1]]:=Block[{f,fa},
	f=traitementf[fct,x];
	If[AdhDomQ[f, x, DirectedInfinity[1]],Return[Limit[f,x->DirectedInfinity[1]]],Return["\[NotExists]"],Return["\[NotExists]"]];
	]

Valeur[fct_,x_Symbol,DirectedInfinity[-1]]:=Block[{f,fa},
	f=traitementf[fct,x];
	If[AdhDomQ[f, x, DirectedInfinity[-1]],Return[Limit[f,x->DirectedInfinity[-1]]],Return["\[NotExists]"],Return["\[NotExists]"]];
	]



Valeur[fct_,x_Symbol,a_]:=Block[{f,fa},
	f=traitementf[fct,x];
	Simplify[f/.x->a]
	]/;Not[NumericQ[a]]


(* signe de la fonction f en une valeur a*)
Signe[f_,x_Symbol,a_]:=If[DomQ[f,x,a],Switch[Sign[Valeur[f,x,a]],1,"+",-1,"-",0,"0"],"/"]

Signe[f_,x_Symbol,a_,symb_]:=If[DomQ[f,x,a],Switch[Sign[Valeur[f,x,a]],1,"+",-1,"-",0,"0"],symb]

SigneDerivee[f_,df_,x_,a_]:=If[DomQ[f,x,a]&&DomQ[df,x,a],Switch[Sign[Valeur[df,x,a]],1,"+",-1,"-",0,"0"],"/"]

SigneDeriveeSeconde[f_,df_,ddf_,x_,a_]:=If[DomQ[f,x,a]&&DomQ[df,x,a]&&DomQ[ddf,x,a],Switch[Sign[Valeur[ddf,x,a]],1,"+",-1,"-",0,"0"],"/"]



(* appartenance a l adherence du domaine?*)
AdhDomQ[f_,x_,a_]:=Block[{adh},
		adh=Adh[Dom[f, x],x];
		adh /. x -> a
		]
 
      
(* ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ _*)
(* determination du domaine de definition de f[x] *)

(* donne des conditions logiques *)
Dom[fct_, x_] := Block[{i,f},
	f=traitementf[fct,x];
	f=f /. Power[u_,Rational[i_Integer,3]]->Sign[u] Abs[u]^(i/3);
      ToRadicals[Reduce[
          And[Or[Reduce[f >= 0, x,Reals] , Reduce[f < 0, x, Reals]] ,
        Reduce[Unequal[Denominator[t], 0], x,Reals] , Reduce[Unequal[Denominator[f] , 0], x, Reals]], x, Reals]]
        ]     

(* domaine de definition d une fonction definie par morceaux*)

Dom[fct_Piecewise, x_] := Block[{arg, cond,i,f},
	f=traitementf[fct,x];
  arg = f[[1]];
  cond = Table[
    Reduce[Dom[arg[[i, 1]], x] && arg[[i, 2]],x,Reals], {i, Length[arg]}];
  Reduce[Apply[Or, cond],x,Reals]
  ]



(* ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ _*)
(*  domaine de definition de f[x] sous forme Ens[domf,x]et s affiche sous forme ensembliste*)
Domaine[f_, x_] := math`Ens[Dom[f, x], x]

(* retourne vrai ou faux selon que a appartient ou non au domaine *)
DomQ[f_,x_,a_]:=Dom[f, x] /. x -> a

(*--------> a effacer, peut etre remplace par Element[a,Dom[f,x]] *)





(* image d une fonction ..... a tester ....*)
Imagef[fct_, x_] := Block[{f,i, cond},
  f=traitementf[fct,x];
  cond = Reduce[f == Global`y, x, Reals];
  
  math`Ensemble[cond /. Equal[x, a_] -> True, Global`y]
  ]

Imagef[fct_Piecewise, x_] := Block[{f,i, cond},
 	f=traitementf[fct,x];
  	(*ajoute une valeur impossible comme valeur par defaut de piecewise*)
	If[f[[2]]==0,f=(f /. f[[2]] -> Infinity)];
  	cond = Reduce[f == Global`y, x, Reals];
    math`Ensemble[cond /. Equal[x, a_] -> True, Global`y]
  ]
  
  

(*  calcule les racines de f (x)                                  *)
Racines[fct_, x_,print_:1] := Block[{f,rac},
	f=traitementf[fct,x];
	rac=Reduce[f == 0, x, Reals]/.C[1]->Global`k;
	rac=Reduce[rac&& Dom[f,x],x,Reals];
	Which[print==0,rac,
		print==1,math`Ens[rac,x],
		print==2, StringForm["racines: `1`",math`Ens[rac,x]]
	]
]

Racines[fct_Piecewise, x_,print_:1] := Block[{f,rac},
	f=traitementf[fct,x];
	(*ajoute une valeur impossible comme valeur par defaut de piecewise*)
	If[f[[2]]==0,f=(f /. f[[2]] -> Infinity)];	
	rac=Reduce[f == 0, x, Reals];
	Which[print==0,rac,
		print==1,math`Ens[rac,x],
		print==2, StringForm["racines: `1`",math`Ens[rac,x]]
	]
	]

EtudeCroissance[fct_,x_Symbol]:=Block[{i},
	f=traitementf[fct,x];
	Column[Select[{Croissance[f,x],Decroissance[f,x]},#=!=Null &]]
]

(* croissance ne fontionne que pour les fonctions elementaires!!! *)
(* retourne les intervalles de croissance sous la forme Ens[cond,x] *)
Croissance[fct_,x_]:= Block[{croiss,liste,f,i},
 	f=traitementf[fct,x];
	croiss = Reduce[D[f, x] >= 0, x, Reals];
	liste = math`Extraitvaleurs[croiss,x];
	(*rajout des valeurs qui adherent au dom de croissance*)
	Do[If[DomQ[f, x, liste[[i]]], croiss=Reduce[Simplify[(croiss  || x == liste[[i]])],x]   ]
  , {i, Length[liste]}];
   If[Length[liste]=!=0,StringForm["La fonction est croissante sur `1`",    math`Ens[croiss, x]/.regleracine]]
]


(* decroissance ne fontionne que pour les fonctions elementaires!!! *)
Decroissance[fct_,x_]:= Block[{croiss,liste,f,i},
 	f=traitementf[fct,x];
	croiss = Reduce[D[f, x] <= 0, x, Reals];
	liste = math`Extraitvaleurs[croiss,x];
		(*rajout des valeurs qui adherent au dom de decroissance*)
	Do[If[DomQ[f, x, liste[[i]]], croiss = Reduce[Simplify[(croiss  || x == liste[[i]])],x]   ]
  , {i, Length[liste]}];
	If[Length[liste]=!=0,StringForm["La fonction est d\[EAcute]croissante sur `1`",    math`Ens[croiss, x]/.regleracine]]
]

(* retourne une chaine de caracteres *)


Parite[fct_, x_] := Block[{a,f,parite},
	f=traitementf[fct,x];
	parite=0;
    If[Reduce[(f /. x -> a) == f /. x -> -a, x, Reals], parite=2];
    If[Reduce[(-f /. x -> a) == f /. x -> -a, x, Reals], parite=1];
  
  Which[parite==0,StringForm["`1` n'est ni paire ni impaire",fct],
  	parite==1,StringForm["`1` est une fonction impaire",fct],
  	parite==2,StringForm["`1` est une fonction paire",fct]
  ]
  
  ]



(* ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ _*)
(* valeurs au bord du domaine de definition de f[x] *)

ValeursDom[f_, x_] := Block[{val},
      val = math`Extraitvaleurs[Dom[f, x],x];
      val = Sort[Intersection[val, val], Less]
      ]

(* graphe cartesien (ensemble) d une  fonction*)

Gf[fct_,x_]:=Block[{f},
	f=traitementf[fct,x];
	math`Ens[Global`y==ReleaseHold[f],x]
	]


(*  CALCUL DE LIMITES  *)

(* notation *)

LimiteNotation[x_, a_] := Underscript["lim", Rule[x, a]]
LimiteNotation[x_, Infinity] := Underscript["lim", Rule[x, StringForm["+`1`",Infinity]]]
LimiteNotation[x_, a_, 1] := Underscript["lim", Underscript[Rule[x, a], ">"]]
LimiteNotation[x_, a_, -1] := Underscript["lim", Underscript[Rule[x, a], "<"]]
(* affichage de l objet Limite *)
Format[Limite[f_,x_,a_]]:=StringForm["`1` `2`",Underscript["lim", Rule[x, a]],f]
Format[Limite[f_,x_,Infinity]]:=StringForm["`1` `2`",Underscript["lim", Rule[x, StringForm["+`1`",Infinity]]],f]
Format[Limite[f_,x_,a_,1]]:=StringForm["`1` `2`",Underscript["lim", Underscript[Rule[x, a], ">"]],f]
Format[Limite[f_,x_,a_,-1]]:=StringForm["`1` `2`",Underscript["lim", Underscript[Rule[x, a], "<"]],f]


(*remplace infini par + infini*)
ruleinfinity=(Infinity -> StringForm["+`1`", Infinity])


(*LIMITE A DROITE*)
CalculLimite[fct_,x_Symbol,a_,1]:=Block[{f},
	f=traitementf[fct,x];
	If[Not[Adh[Simplify[Dom[f, x] && x > a], x] /. x -> a],Return[{"\[NotExists]"}]];
	ComplexExpand[Limit[f,x->a,Direction->-1]]
]
(*limite a droite de +infini n a pas de sens*)
CalculLimite[fct_,x_Symbol,Infinity,1]:=Block[{f},
	Return["\[NotExists]"]
]
(*limite a gauche de -infini n a pas de sens*)
CalculLimite[fct_,x_Symbol,-Infinity,-1]:=Block[{f},
	Return["\[NotExists]"]
]

(*LIMITE A GAUCHE*)
CalculLimite[fct_,x_Symbol,a_,-1]:=Block[{f},
	f=traitementf[fct,x];
	If[Not[Adh[Simplify[Dom[f, x] && x < a], x] /. x -> a],Return["\[NotExists]"]];
	ComplexExpand[Limit[f,x->a,Direction->1]]
]
(*limite en + infini*)
CalculLimite[fct_,x_,Infinity]:=Block[{f,vallim},
	f=traitementf[fct,x];
	If[Not[AdhDomQ[f,x,Infinity]],Return[{-2,"\[NotExists]"}]];
	vallim=ComplexExpand[Limit[f,x->DirectedInfinity[1]]];
	(*If[Not[NumericQ[a]],Return[vallim]];*)
	If[Head[vallim]==Interval,Return[{-2,"\[NotExists]"}]];
	If[Or[Element[vallim, Reals] , vallim == DirectedInfinity[1] , vallim == DirectedInfinity[-1]],Return[{0,vallim}],Return[{-2,"\[NotExists]"}],{-2,vallim} ]
]

(*limite en - infini*)
CalculLimite[fct_,x_,-Infinity]:=Block[{f,vallim},
	f=traitementf[fct,x];
	If[Not[AdhDomQ[f,x,-Infinity]],Return[{-2,"\[NotExists]"}]];
	vallim=ComplexExpand[Limit[f,x->DirectedInfinity[-1]]];
	(*If[Not[NumericQ[a]],Return[vallim]];*)
	If[Head[vallim]==Interval,Return["\[NotExists]"]];
	If[Or[Element[vallim, Reals] , vallim == DirectedInfinity[1] , vallim == DirectedInfinity[-1]],Return[{0,vallim}],Return["\[NotExists]"],vallim ]
]
(*essai de traitement des variables dans un calcul de limite, mais quid de f...*)
CalculLimite[fct_, x_Symbol, a_Symbol]:=Block[{f,vallim},
	f=traitementf[fct,x];
	vallim=ComplexExpand[Limit[f, x -> a]];
	Return[{0,vallim}]
]
	
(*  calcul d une limite de f en a *)
(*  {-2} := limite n existe pas *)
(*  {-1, lim} :=  limgauche existe*)
(*  {0, lim} := limdroite = limgauche *)
(*  {1, lim} := limdroite existe *)
(*  {2, limg, limd} := limdroite est different de limgauche *)
(*  domaine de definition de f[x] sous forme ensembliste*)
CalculLimite[fct_, x_, a_] := Block[{f,vallim, glim, dlim, retour,vlimi},
		f=traitementf[fct,x];
	  	(*si a n adhere pas au domaine c est fini*)
      	If[Not[AdhDomQ[f,x,a]], Return[{-2,"\[NotExists]"}]];

        vallim = ComplexExpand[Limit[f, x -> a]];

      	glim = ComplexExpand[Limit[f, x -> a, Direction -> 1]];

    	dlim = ComplexExpand[Limit[f, x -> a, Direction -> -1]];

    	  (* si limite reelle = a gauche et droite *)
    	  If[And[glim == dlim  , Element[glim, Reals]], Return[{0, glim}]];
    	  (* si limite infinie = a gauche et droite *)
    	  If[And[glim == dlim , Or[glim == DirectedInfinity[1] ,glim == DirectedInfinity[-1]]], Return[{0,glim}]];
    	  retour = 0;
    	  If[Or[Element[glim, Reals] , glim == DirectedInfinity[1] , glim == DirectedInfinity[-1]], retour = 1];
    	  If[Or[Element[dlim, Reals], dlim == DirectedInfinity[1],  dlim ==DirectedInfinity[-1]], retour = retour + 2];
      
     	 Which[retour == 0, {-2,"\[NotExists]"}, retour == 1, {-1, glim}, 
     	 retour == 2, {1, dlim}, retour == 3, {2, glim, dlim}]
    ]

(* affiche la limite presentee sous forme imprimable  *)
Calcule[Limite[fct_,x_,a_]]:=Block[{clim,texte,limite,f},
	f=traitementf[fct,x];
	limite=Limite[fct,x,a];
	clim=CalculLimite[f,x,a];
	texte=Which[clim[[1]]==-2,
	StringForm["`1` = `2`",limite,clim[[2]]],
	clim[[1]]==-1,
	StringForm["`1` = `2`",Limite[fct,x,a,-1],clim[[2]]/.ruleinfinity],
	clim[[1]]==1, 
	StringForm["`1` = `2`",Limite[fct,x,a,1],clim[[2]]/.ruleinfinity],
	clim[[1]]==0,
	StringForm["`1` = `2`",limite,clim[[2]]/.ruleinfinity],
	clim[[1]]==2,
	StringForm["`1`",Piecewise[{{StringForm["`1` = `2`",Limite[fct,x,a,-1],clim[[2]]/.ruleinfinity], " "}, {StringForm["`1` = `2`",Limite[fct,x,a,1],clim[[3]]/.ruleinfinity], "  "}}]]
	];
	texte
	]


Calcule[Limite[fct_,x_Symbol,a_Symbol]]:=Block[{f,clim,limite},
	f=traitementf[fct,x];
	clim=CalculLimite[f,x,a];
	StringForm["`1` = `2`",Limite[fct,x,a],clim[[2]]/.ruleinfinity]
]


Calcule[Limite[fct_,x_Symbol,a_,1]]:=Block[{f,clim,limite},
	f=traitementf[fct,x];
	clim=CalculLimite[f,x,a,1];
	StringForm["`1` = `2`",Limite[fct,x,a,1],clim/.ruleinfinity]
]



Calcule[Limite[fct_,x_Symbol,a_,-1]]:=Block[{f,clim,limite},
	f=traitementf[fct,x];
	clim=CalculLimite[f,x,a,-1];
	StringForm["`1` = `2`",Limite[fct,x,a,-1],clim/.ruleinfinity]
]


(*intersection axe X *)

InterX[fct_,x_]:= Block[{f,texte="Gf \[Intersection] X = ",reponse,i,texteint,textereponse},
	f=traitementf[fct,x];
	reponse=math`Extraitvaleurs[Racines[f, x,0],x];
	texteint=Table[0,{Length[reponse]}];
	If[reponse=={}, textereponse=StringJoin[texte," { }"],
	Do[
	texteint[[i]]=StringForm["(`1`,`2`)",reponse[[i]],f/.x->reponse[[i]]] ,
	{i,Length[reponse]}
	];
	
	textereponse=StringForm["`1`{ ",texte];
	Do[
	textereponse=StringForm["`1``2`",textereponse,texteint[[i]]];
	If[i!=Length[reponse],textereponse=StringForm["`1` , ",textereponse ]],
	{i,Length[reponse]}
	];
	textereponse=StringForm["`1` }",textereponse ]
	];
	textereponse
	]
	
(* intersection axe Y *)
InterY[fct_,x_]:=Block[{f,reponse,textereponse,texte="Gf \[Intersection] Y = "},
	f=traitementf[fct,x];
    If[Not[DomQ[f,x,0]], Return[StringJoin[texte," { }"]]];
    textereponse=StringForm["`1`{ (0,`2`) }",texte,f/.x->0];
    textereponse
    ]
    

(*  recherche des asymptotes verticales                                  *)

AVx[fct_,x_,a_,print_:1]:=Block[{f,valdomaine,resultatlimite,n},
	f=traitementf[fct,x];
	
      resultatlimite = CalculLimite[f, x, a];
      n = resultatlimite[[1]];
      Which[n == 0,
        If[Or[resultatlimite[[2]] == DirectedInfinity[1] ,resultatlimite[[2]] == DirectedInfinity[-1]],
           If[print==1,Print[StringForm["AV \[Congruent] `1` = `2`", x, ToRadicals[a]]]];
           Return[{a}]
           ],
        n == -1,
        If[Or[resultatlimite[[2]] == DirectedInfinity[1], resultatlimite[[2]] == DirectedInfinity[-1]],
        	If[print==1,Print[StringForm["AV \[Congruent] `1` = `2` \[AGrave] gauche", x, ToRadicals[a]]]];
        	Return[{a}]
        	],
        n == 1,
        If[Or[resultatlimite[[2]] == DirectedInfinity[1], resultatlimite[[2]] == DirectedInfinity[-1]],
         If[print==1,Print[StringForm["AV \[Congruent] `1` = `2` \[AGrave] droite", x, ToRadicals[a]]]];
         Return[{a}]
         ],
        n == 2,
        If[Or[resultatlimite[[2]] == DirectedInfinity[1] , resultatlimite[[2]] == DirectedInfinity[-1] ,
        resultatlimite[[3]] == DirectedInfinity[1] , resultatlimite[[3]] == DirectedInfinity[-1]],
         If[print==1,Print[StringForm["AV \[Congruent] `1` = `2`", x, ToRadicals[a]]]];
         Return[{a}];
         ]
      ];
      {}
	]


AV[fct_, x_,print_:1] := Block[{av,f,n,i,avx={}, valdomaine = {},lesav={},pasdav = "pas d'asymptote verticale"},
	f=traitementf[fct,x];
    valdomaine = ValeursDom[f, x];
    If[Length[valdomaine] == 0, If[print==1,Print[pasdav]];Return[math`Ens[False,x]]];
    Do[
    	If[print==1,Print[Calcule[Limite[fct, x, valdomaine[[i]]]]]];
 
    	 If[Not[AdhDomQ[f,x,valdomaine[[i]]]], Continue[]];
    	 avx=AVx[f,x,valdomaine[[i]],print];
 		   	lesav=Join[lesav,avx];
      , {i, Length[valdomaine]}];
      
      If[Length[lesav]>=1,
      	Table[av=math`Droite[x == lesav[[i]],"AV",Red];math`Trait[av]=1;av,{i,1,Length[lesav]}],
      	math`Ens[False,x]
      	]
    ]
 
    
       (*a modifier devrait utiliser la fonction calcullimite....*)
AODroite[f_, x_] := Block[{liminf, a, b,ao},
    liminf = ComplexExpand[Limit[f, x -> DirectedInfinity[1]]];
    a = ComplexExpand[Limit[f/x, x -> DirectedInfinity[1]]];
    b = ComplexExpand[Limit[f - a*x, x -> DirectedInfinity[1]]];
    
    If[Element[liminf, Reals],ao=math`Droite[Global`y == liminf,"AH",Red];math`Trait[ao]=1; Return[ao]];
    If[Element[b, Reals] && Element[a, Reals] && !MatchQ[f, a_.  x + b_.], ao=math`Droite[Global`y == a*x + b,"AO",Red];math`Trait[ao]=1;Return[ao]];
    Return[math`Ens[False,x]]
    ]
       

AOGauche[f_, x_] := Block[{liminf, a, b,ao},
    liminf = ComplexExpand[Limit[f, x -> DirectedInfinity[-1]]];
    a = ComplexExpand[Limit[f/x, x -> DirectedInfinity[-1]]];
    b = ComplexExpand[Limit[f - a*x, x -> DirectedInfinity[-1]]];
    If[Element[liminf, Reals], ao=math`Droite[Global`y == liminf,"AH",Red];math`Trait[ao]=1; Return[ao]];
    If[Element[b, Reals] && Element[a, Reals] && !MatchQ[f, a_.  x + b_.], ao=math`Droite[Global`y == a*x + b,"AO",Red];math`Trait[ao]=1;Return[ao]];
    Return[math`Ens[False,x]]
    ]

  

 (*  recherche des asymptotes obliques                            *)
AO[fct_, x_,print_:1] := Block[{f,type,ad,ag,adroite, agauche},
	f=traitementf[fct,x];
	(*presente le calcul de la limite*)
    If[print==1,Print[Calcule[Limite[fct, x, DirectedInfinity[1]]]];
    	Print[Calcule[Limite[fct, x, DirectedInfinity[-1]]]]
    ];
	If[print==2,Print[limites`Sol[Limite[fct, x, DirectedInfinity[1]]]];
    	Print[limites`Sol[Limite[fct, x, DirectedInfinity[-1]]]]
    ]
    (*si f definie vers +infini, calcul limite*)
    If[DomQ[f,x,Infinity], ad=AODroite[f, x];adroite = ad[[1]]];
    (*idem vers - infini*)
    If[DomQ[f,x,-Infinity], ag=AOGauche[f, x];agauche = ag[[1]]];
    If[FreeQ[adroite, Global`x], type = "AH", type = "AO"];
    If[And[adroite == agauche , Head[ad]==math`Droite], 
    	 If[print==1,Print[type, " \[Congruent] ", adroite]];
    	 Return[ad]];
    If[Head[ad]==math`Droite, 
    	 If[print==1,Print[type, " \[Congruent] ", ad, " \[AGrave] droite"]]];
    If[FreeQ[agauche, Global`x], type = "AH", type = "AO"];
    If[ Head[ag]==math`Droite, 
    	 If[print==1,Print[type, " \[Congruent] ", ag, " \[AGrave] gauche"]]];
    ]

(*asymptotes*)

Asymptotes[fct_,x_]:=Block[{i},
	Print[Framed[StringForm["f(x) = `1`",fct]]];
	Print["Dom f = ",Domaine[fct,x]];
	AV[fct,x];
	AO[fct,x,2];
	]
 
(*  determine la derivee de f (x)                                  *)
Derivee[fct_, x_] := Block[{f},
		f=ReleaseHold[fct];
		If[f==Abs[x],Abs[x]/x,
		Together[D[f, x]],Together[D[f, x]]]
	]


(* tangente  *)
Tangente[f_,x_,a_]:=Block[{fa,df,dfa},
	(*si la valeur a n appartient pas au domaine, pas de tangente*)
	If[ Not[DomQ[f,x,a]],Return[math`Ens[False, x]]];
	(*si la valeur n appartient pas au domaine de la derivee la tangente est verticale (ce qui est faut...a completer !!!)*)
	df = Derivee[f, x];
	If[Not[DomQ[df,x,a]],Return[math`Droite[Global`x==a]]];
	(*calcul tangente*)
	fa=f/.x->a;
	dfa = df/.x->a;
	math`Droite[Reduce[Global`y-fa==dfa (x-a),Global`y,Reals],"Tgte",Darker[Green]]
	]
	
DetailTangente[f_, x_, a_] := Block[{ff, df, fa, dfa, tgte},
  Print["f(x) = ",f,"    et a = ",a/.math`regleracine];
  ff = ReleaseHold[f]/.Curt -> RacineCubique;
  (*a n appartient pas au domaine - pas de tangente*)
  If[ Not[DomQ[ff,x,a]],Print[a," \[NotElement] dom f"];Return[]];
  
  fa = (ff /. x -> a) /. math`reglelog;
  Print["f(a) = ", fa];
  df = Derivee[ff, x];
  Print["f'(x) = ", df];
  (*si la derivee n existe pas, tangente verticale --> a completer pour d autres cas...*)
  If[Not[DomQ[df,x,a]],Print["Tangente verticale"];Return[Presente[Tangente[ff,x,a]]]];
  dfa = df /. x -> a;
  dfa = dfa /. math`regleracine;
  Print["f'(a) = ", dfa];
  Print["Tgte \[Congruent]  y - f(a) \[Equal] f'(a) (x-a)"];
  Print["Tgte \[Congruent] ", Global`y - fa == dfa (x - a)];
  tgte = Tangente[ff /. math`regleracine, x, a];
  Presente[Tangente[ff,x,a]]
 
  ]	
	

MaxQ[f_, x_, a_] := Block[{l1, l2, df},
    If[Not[DomQ[f,x,a]], Return[False]];
    If[And[(D[f, x] == 0 /. x -> a) , (D[f, {x, 2}] < 0 /. x -> a)], Return[True]];
    df = Derivee[f, x];
    l1 = Limit[Abs[df]/df, x -> a, Direction -> 1];
    l2 = Limit[Abs[df]/df, x -> a, Direction -> -1];
    If[And[l1 == 1 , l2 == -1], True, False, False]
    ]

MinQ[f_, x_, a_] := Block[{l1, l2, df},
    If[Not[DomQ[f,x,a]], Return[False]];
    If[And[(D[f, x] == 0 /. x -> a) , (D[f, {x, 2}] > 0 /. x -> a)], Return[True]];
    df = Derivee[f, x];
    l1 = Limit[Abs[df]/df, x -> a, Direction -> 1];
    l2 = Limit[Abs[df]/df, x -> a, Direction -> -1];
    If[And[l1 == -1 , l2 == 1], True, False, False]
    ]

Extremums[f_, x_,print_:1] := Block[{leszeros,lextremums},
	lextremums={};
	(*lextremums donne la liste des abscisses pour ls extremums*)
   leszeros = math`Extraitvaleurs[Racines[Together[D[f, x]], x,0],x];
    If[leszeros == {}, Return[]];
    Do[
      If[MaxQ[f, x, leszeros[[i]]],
      	lextremums=Append[lextremums, ToRadicals[leszeros[[i]]]];
      If[print==1,Print[StringForm[" Max : (`1`,`2`)",ToRadicals[leszeros[[i]]], ToRadicals[Simplify[f /. x ->leszeros[[i]]]]]]]];
      If[MinQ[f, x, leszeros[[i]]], 
     	lextremums=Append[lextremums, ToRadicals[leszeros[[i]]]];
      If[print==1,Print[StringForm[" Min : (`1`,`2`)", ToRadicals[leszeros[[i]]], ToRadicals[Simplify[f /. x -> leszeros[[i]]]]]]]]
      , {i, Length[leszeros]}];
      lextremums
    ]
    
Inflexions[f_, x_] := Block[{leszeros},
   leszeros = math`Extraitvaleurs[Racines[Together[D[f, {x,2}]], x,0],x];
    If[leszeros == {}, Return[]];
    Do[
      If[InflexionQ[f, x, leszeros[[i]]], 
      Print[StringForm[" I : (`1`,`2`)",ToRadicals[leszeros[[i]]], ToRadicals[Simplify[f /. x ->leszeros[[i]]]]]]]
      , {i, Length[leszeros]}]
    ]

InflexionQ[f_, x_, a_] := Block[{l1, l2, df, ddf},
    If[!(DomQ[f,x,a]), Return[False]];
    ddf = DeriveeSeconde[f, x];
    l1 = Limit[Abs[ddf]/ddf, x -> a, Direction -> 1];
    l2 = Limit[Abs[ddf]/ddf, x -> a, Direction -> -1];
    If[l1*l2 == -1, True, False, False]
    ]
    
(*  determine la derivee seconde de f (x)                                  *)
DeriveeSeconde[f_, x_] := Together[D[f, {x, 2}]]

(*							TABLEAUX DE SIGNES !!!!!!*)




(* donne la liste des valeurs a mettre dans un tableau de signes*)
ListeValeurs[f_,x_]:=Block[{valdomaine={},valracines={},valdenom={}},
	valdomaine = ValeursDom[f, x];
    valracines = math`Extraitvaleurs[Racines[f,x,0],x];
    valdenom = math`Extraitvaleurs[Racines[Together[f],x,0],x];
    liste = Join[valdomaine, valracines, valdenom];
    liste = Sort[Intersection[liste, liste], Less]
	]
	
	
 (* cree la liste des valeurs *)
ListeValeursTableau[liste_]:=Block[{i=0,l},
    l=liste;
    Do[If[Head[l[[i]]] == Root, l[[i]] = Chop[ToRadicals[l[[i]]]]], {i,1, Length[l]}];
    
    Do[If[Or[Head[l[[i]]] == Root ,  LeafCount[l[[i]]] > 15], 
    l[[i]] = Chop[N[l[[i]]]]], {i, Length[l]}];
    
    Table[
        If[i == 1, "    ",
          If[EvenQ[i], l[[i/2]],
            If[And[OddQ[i] , i != 1 , i != 2*Length[l] + 1], "    ",
              If[i == 2*Length[l] + 1, "    "]
              ]
            ]
          ],
        {i, 2*Length[l] + 1}]
        ]

(*  affiche le tableau de signe de f              *)

Options[TableaudeSignes]={Valeurs->False}
Options[TableaudeSignesComplet]={Valeurs->False}

TableaudeSignes[fct_, x_] := Block[{f,test,i=0,listesignes, listevaleurs, table, liste = {}},
     f=traitementf[fct,x]; 
    liste=ListeValeurs[f,x];
    (* liste simple des valeurs*)
  
    (* cree la liste des valeurs a mettre dans le tableau avec les colonnes entre*)
    listevaleurs=ListeValeursTableau[liste];
    listesignes=ListeSignes[f,x,liste,True];
  
    (* rajoute x et f (x) et affiche sous forme de tableau *)
    table = {Join[{x}, listevaleurs], Join[{fct}, listesignes]};
    GridBox[table, GridFrame -> True, RowLines -> True, ColumnLines -> True] // DisplayForm
    ]

TableaudeSignes[l_List,x_]:=TableaudeSignes[l,x,Valeurs->True]
    
TableaudeSignes[listef_List,x_,OptionsPattern[]]:=Block[{f,n,liste={},lv,lsignes={},tableau,lignes,valeursoui},
	valeursoui=OptionValue[Valeurs];
	If[valeursoui=!=True && valeursoui=!=False,Return["l'option Valeurs doit etre True ou False!"]];
	n=Length[listef];
	(*met n importe quoi dans lsignes pour initialiser -- pas joli je sais..;*)
	lsignes=Table[i, {i, n}];
	Do[liste=Join[liste,ListeValeurs[listef[[i]],x]]
		,{i,1,n}];
	(*tri de la liste*)
    liste = Sort[Intersection[liste, liste], Less];
    lv=ListeValeursTableau[liste];
	Do[lsignes[[i]]=ListeSignes[listef[[i]],x,liste,valeursoui]
		,{i,1,n}];
	Do[lignes[i]=Prepend[lsignes[[i]],listef[[i]]],{i,1,n}];

	tableau=Prepend[Table[lignes[i],{i,n}],Prepend[lv,x]];
	GridBox[tableau, GridFrame -> True, RowLines -> True, ColumnLines -> True] // DisplayForm
]

TableaudeSignesComplet[fct_,x_,OptionsPattern[]]:=Block[{f,liste,num,den,numl,denl,valeursoui},
	   f=traitementf[fct,x];
	   
	   valeursoui=OptionValue[Valeurs];
	   (*si f est une somme, mettre au meme denominateur*)
	   If[Head[f]==Plus,f=Together[f]];
	   num=Numerator[f];
	   den=Denominator[f];
	   If[Head[num]==Times,
	   	numl=(Apply[List, num]),
	   	numl={num},
	   	numl={num}
	   ];
	   If[Head[den]==Times,
	   	denl=(Apply[List, den]),
	   	denl={den},
	   	denl={den}
	   ];
	   liste=Join[numl,denl];
	   liste=Replace[liste,Power[e_,-1]-> e, 1];
	   liste=Append[liste,fct];
	   TableaudeSignes[liste,x,Valeurs->valeursoui]
]


TableaudeSignesD[fct_,dfct_, x_] := Block[{df,f,test,i=0,listesignes, listevaleurs, table, liste = {}},
	f=traitementf[fct,x]; 
	df=ReleaseHold[dfct]/.Curt -> RacineCubique; 
    liste=ListeValeurs[df,x];
    liste=Join[liste,ValeursDom[f,x]];
    liste = Sort[Intersection[liste, liste], Less];
    
    (* creation de la liste des signes *)
    listesignes = Table[
        If[i == 1, 
        If[Length[liste] == 0,
            SigneDerivee[f,df,x,0]
            ,
            SigneDerivee[f,df,x,liste[[i]] - 1]
            ]
          ,
          
          If[EvenQ[i],
            test = liste[[i/2]];            
            If[DomQ[f,x,test]&& DomQ[df,x,test],
              If[Or[Head[test] == Root , Head[test] == Complex,LeafCount[test] > 15], 
              Chop[N[Simplify[Valeur[df,x,test]]]],
                Simplify[Valeur[df,x,test]], Simplify[Valeur[df,x,test]]], "|","|"]
            ,
           
            If[OddQ[
                i] && i != 1 && i != 2*Length[liste] + 1, 
                test = (liste[[(i - 1)/2]] + liste[[(i + 1)/2]])/2;
              SigneDerivee[f,df,x,test],             
              
              If[i == 2*Length[liste] + 1, test = liste[[Length[liste]]] + 1;
                SigneDerivee[f,df,x,test]
                ]
              ]
            ]
          
          ]
        
        , {i, 2*Length[liste] + 1}];
    
    
    
    (* cree la liste des valeurs *)
    listevaleurs=ListeValeursTableau[liste];
    
    
    (* rajoute x et f (x) et affiche sous forme de tableau *)
    table = {Join[{"x"}, listevaleurs], Join[{dfct}, listesignes]};
    GridBox[table, GridFrame -> True, RowLines -> True, ColumnLines -> True] // DisplayForm
    ]       
    
TableaudeSignesDD[f_,df_,ddf_, x_] := Block[{valeur,test,i=0,listesignes, listevaleurs, table, liste = {}},
      
    liste=ListeValeurs[ddf,x];
    liste=Join[liste,ValeursDom[f,x],ValeursDom[df,x]];
    liste = Sort[Intersection[liste, liste], Less];
    
    (* creation de la liste des signes *)
    listesignes = Table[
        If[i == 1, 
        If[Length[liste] == 0,
            SigneDeriveeSeconde[f,df,ddf,x,0]
            ,
            SigneDeriveeSeconde[f,df,ddf,x,liste[[i]] - 1]
            ]
          ,
          
          If[EvenQ[i],
            test = liste[[i/2]];   
                
            If[DomQ[f,x,test]&& DomQ[df,x,test]&& DomQ[ddf,x,test],
            	            valeur=Simplify[Valeur[ddf,x,test]];
            	            valeur=If[LeafCount[valeur]>15,Chop[N[Simplify[valeur]]],valeur,valeur];  
              If[Or[Head[test] == Root , Head[test] == Complex,LeafCount[test] > 15], 
              	Chop[N[Simplify[valeur]]],
                Simplify[valeur], Simplify[valeur]], "|","|"]
            ,
           
            If[OddQ[
                i] && i != 1 && i != 2*Length[liste] + 1, 
                test = (liste[[(i - 1)/2]] + liste[[(i + 1)/2]])/2;
              SigneDeriveeSeconde[f,df,ddf,x,test],             
              
              If[i == 2*Length[liste] + 1, test = liste[[Length[liste]]] + 1;
                SigneDeriveeSeconde[f,df,ddf,x,test]
                ]
              ]
            ]
          
          ]
        
        , {i, 2*Length[liste] + 1}];
    
    
    
    (* cree la liste des valeurs *)
    listevaleurs=ListeValeursTableau[liste];
    
    
    (* rajoute x et f (x) et affiche sous forme de tableau *)
    table = {Join[{"x"}, listevaleurs], Join[{ddf}, listesignes]};
    GridBox[table, GridFrame -> True, RowLines -> True, ColumnLines -> True] // DisplayForm
    ]
    
    
    
TableauRecapitulatif[f_, x_] := Block[{domdeddf, domdedf, test, clim,partdom,
  df, ddf, domdef, listesignes, listesignesdf,listesignesddf, listevaleurs, table, liste = {}, valdomaine = {}, 
      valracines = {}, valdenom = {}, listedf = {}, listeddf = {}, commentaires, ao, n,i=0},
    df = Derivee[f, x];
    ddf = DeriveeSeconde[f, x];
    
    domdef = Dom[f, x];
    valdomaine = ValeursDom[f, x];
    valracines = math`Extraitvaleurs[Racines[f,x,0],x];
    valdenom = math`Extraitvaleurs[Racines[Together[f],x,0],x];
    liste = Join[valdomaine, valracines, valdenom];
    liste = Sort[Intersection[liste, liste], Less];
    
    domdedf = Simplify[Dom[df, x]&& domdef];
valdomaine = ValeursDom[df, x];
valracines = math`Extraitvaleurs[Racines[df,x,0],x];
valdenom = math`Extraitvaleurs[Racines[Together[df],x,0],x];
listedf = Join[valdomaine, valracines, valdenom];
listedf = Sort[Intersection[listedf, listedf], Less];
    

    domdeddf = Simplify[Dom[ddf, x] && Dom[df, x] && domdef];
valdomaine = ValeursDom[ddf, x];
valracines = math`Extraitvaleurs[Racines[ddf,x,0],x];
valdenom = math`Extraitvaleurs[Racines[Together[ddf],x,0],x];
listeddf = Join[valdomaine, valracines, valdenom];
listeddf = Sort[Intersection[listeddf, listeddf], Less];

    liste = Flatten[Join[{0},liste, listedf, listeddf]];
liste = Sort[Intersection[liste, liste], Less];
        
    
    (* creation de la liste des signes *)
    listesignes = ListeSignes[f, x, liste,True];
    
    (* creation de la liste des signes *)
    listesignesdf = ListeSignes[df, x, liste,True];
    
    (* creation de la liste des signes *)
    listesignesddf = ListeSignes[ddf, x, liste,True];
    
    
    commentaires = Table[" ", {i, 2*Length[liste] + 1}];
    Do[If[And[EvenQ[i] , MaxQ[f, x, liste[[i/2]]]], commentaires[[i]] = "Max"; Continue[]];
      If[And[EvenQ[i] , MinQ[f, x, liste[[i/2]]]], commentaires[[i]] = "Min"; Continue[]];
      If[And[EvenQ[i] , InflexionQ[f, x, liste[[i/2]]]], commentaires[[i]] = "I"; Continue[]]
      , {i, 2*Length[liste] + 1}];
    
    ao = AOGauche[f, x];
    commentaires = Join[{If[Head[ao] ===Droite, ao[[1]], " "]}, commentaires];
    ao = AODroite[f, x];
    commentaires = Join[commentaires, {If[Head[ao] ===Droite, ao[[1]], " "," "]}];
    
    clim=CalculLimite[f,x,-Infinity];
    partdom=clim[[1]];
    (*clim[[1]]=-2 veut dire n existe ps?*)
    If[clim[[1]]==-2,finf1="/",finf1 = clim[[2]]];
    clim=CalculLimite[df,x,-Infinity];
    If[Or[clim[[1]]==-2,partdom==-2] ,dfinf1="/",dfinf1 = clim[[2]]];
    clim=CalculLimite[ddf,x,-Infinity];
    If[Or[clim[[1]]==-2,partdom==-2],ddfinf1="/",ddfinf1 = clim[[2]]];
   
    clim=CalculLimite[f,x,Infinity];
    partdom=clim[[1]];
    If[clim[[1]]==-2,finf2="/",finf2 = clim[[2]]];
    clim=CalculLimite[df,x,Infinity];
    If[Or[clim[[1]]==-2,partdom==-2],dfinf2="/",dfinf2 = clim[[2]]];
    clim=CalculLimite[ddf,x,Infinity];
    If[Or[clim[[1]]==-2,partdom==-2],ddfinf2="/",ddfinf2 = clim[[2]]];
       
    
    
    
    (* cree la liste des valeurs *)
    listevaleurs=ListeValeursTableau[liste];
    
    
    (* rajoute x et f (x) et affiche sous forme de tableau *)
    table = {
    Join[{"x", -Infinity}, listevaleurs, {"+\[Infinity]"}], Join[{"f(x)", finf1}, listesignes, {finf2}], Join[{" "}, commentaires], 
        Join[{"pente", dfinf1}, listesignesdf, {dfinf2}], Join[{"concavit\[EAcute]", ddfinf1}, listesignesddf, {ddfinf2}]};
    GridBox[table, GridFrame -> True, RowLines -> True, ColumnLines -> True] // DisplayForm
      
    ]  


Signedef[f_, x_, a_] := Block[{domdef, fa},
    domdef = Dom[f, x];
    
    If[domdef /. x -> a,
      fa = (f /. x -> a);
      Switch[Sign[Simplify[fa]], 1, "+", -1, "-", 0, 0], "|"]
    ]
    
Valeurdef[f_, x_, a_] := Block[{domdef, fa},
    domdef = Dom[f, x];
    
    If[domdef /. x -> a,
      fa = (f /. x -> a);
      Simplify[fa], "|"]
    ]
    
    
ListeSignes[f_, x_, {},True] := {Signedef[f, x, 0]}

ListeSignes[f_, x_, liste_,valeursoui_] := Block[{valf,n, valeurs,i=0},
    n = 2*Length[liste] + 1;
    valeurs = Table["?", {i, n}];
    Do[
    If[i == 1, valeurs[[i]] = liste[[i]] - 1; Continue[]];
    If[EvenQ[i], valeurs[[i]] = liste[[i/2]]; Continue[]];
    If[OddQ[i] && i != 1 && i != n,
          valeurs[[i]] = (liste[[(i - 1)/2]] + liste[[(i + 1)/2]])/2; Continue[]];
    If[i == n, valeurs[[i]] = liste[[Length[liste]]] + 1; Continue[]]
    , {i, n}];
    Table[If[EvenQ[i] &&valeursoui,
    		valf=Valeurdef[f, x, valeurs[[i]]];
    		valf=If[LeafCount[valf]>15,Chop[N[Simplify[valf]]],valf,valf],
    	Signedef[f, x, valeurs[[i]]]],
    	 {i, n}]
    ]



Etudef[fct_,x_] := Block[{f,a,gf,df,ddf},
    f=traitementf[fct,x];
    Print["f(x) = ", fct];
    
    Print[Style["1. Domaine de d\[EAcute]finition", Underlined]];
    Print["Dom f = ", Domaine[f, x]];
    
    Parite[fct,x];
    
    Print[Style["2. Signe de f", Underlined]];
    
    Print[TableaudeSignes[fct,x]];
    
    Print[Style["3. Limites et asymptotes", Underlined]];
    

    AV[fct,x];
    AO[fct,x];
      
    Print[Style["4. Intersection avec les axes", Underlined]];
  
    Print[InterX[fct,x]];
    Print[InterY[fct,x]];
 
    Print[Style["5. Etude de f'", Underlined]];
    
    df = Together[D[ReleaseHold[fct], x]];
    Print["f'(x) = ", Derivee[fct,x]];
    Print[TableaudeSignesD[fct,df,x]];
    Extremums[f,x];
     
    Print[Style["6. Etude de f\"", Underlined]];
    
    
    ddf = Together[D[ReleaseHold[fct], {x, 2}]];
    Print["f\"(x) = ", ddf];
    Print[TableaudeSignesDD[f,df,ddf,x]];
    Inflexions[f,x]; 
    
	Print[Style["7.Tableau r\[EAcute]capitulatif", Underlined]];
        
    Print[TableauRecapitulatif[f,x]];
    
	Print[Style["8. Graphe de f", Underlined]];

   Graphef[fct,x]
    ]

Etude[1,fct_,x_]:=Block[{f,a,gf},
    f=traitementf[fct,x];
    Print["f(x) = ", fct];
    
    Print[Style["1. Domaine de d\[EAcute]finition", Underlined]];
    Print["Dom f = ", Domaine[f, x]];
    

    
    Print[Style["2. Image de f", Underlined]];
    
    Print[Imagef[fct,x]];
    
    Print[Style["3. Limites et asymptotes", Underlined]];
    

    AV[fct,x];
    AO[fct,x];
      
    Print[Style["4. Racines", Underlined]];
  
    Print[Racines[fct,x]];
 
	Print[Style["5. Graphe de f", Underlined]];

   Print[Graphef[fct,x]]
    ]



Graphef[fct_,x_,options_:(Frame->False)]:=Block[{range,f,g,aog,aod,graphef,ens},
	f=traitementf[fct,x];
	ens=math`Ens[Global`y==fct,x];
	graphef=math`Graphe[ens];
	math`Couleur[ens]=math`CouleurparDefaut;
	If[Periode[f,x]=={},
		Show[{math`Graphe[AODroite[f,x]],math`Graphe[AOGauche[f,x]] ,graphef,math`Graphe[AV[f,x,0]]}],
		math`Graphe[math`Ens[Global`y==f,x],options],
		math`Graphe[math`Ens[Global`y==f,x],options]]
	]

(*	math`Axesfleches[If[Periode[f,x]=={},
		Show[{math`Graphe[AODroite[f,x]],math`Graphe[AOGauche[f,x]] ,math`Graphe[math`Ens[Global`y==fct,x]],math`Graphe[AV[f,x,0]]},options,PlotRange->{math`cadrex,math`cadrey},math`reglesgraphe],
		math`Graphe[math`Ens[Global`y==f,x],options],
		math`Graphe[math`Ens[Global`y==f,x],options]]*)


Graphef[fct_Piecewise,x_,options_:(Frame->False)]:=Block[{fcti,part,ens,color,i,listeg,listval,f,g,aog,aod,pt,pts={}},
	f=traitementf[fct,x];
	ens=math`Ens[Global`y==fct,x];
	Couleur[ens]=math`CouleurparDefaut;
	(*ajoute une valeur impossible comme valeur par defaut de piecewise*)
	If[f[[2]]==0, f[[2]] = Infinity];
	(*listeg={Graphique[AODroite[f,x]],Graphique[AOGauche[f,x]] ,Graphique[Ens[Global`y==f,{x,Global`y}]],Graphique[AV[f,x,0]]}*)
	listeg={math`Graphe[ens],math`Graphe[AV[fct,x,0]]};
	
	Do[
		part=f[[1,j]];
		listval=math`Extraitvaleurs[part[[2]],x];
		listval=Sort[Intersection[listval, listval], Less];
		If[listval!={}  ,
		Do[
			color=If[math`CouleurparDefaut==Black,White,Darker[Red],Darker[Red]];
			If[DomQ[part[[1]],x,listval[[i]]] && Element[listval[[i]],math`Ensemble[part[[2]],x]],color=math`CouleurparDefaut];
			pt=math`Pt[listval[[i]],part[[1]]/.x->listval[[i]]];
			math`Taille[pt] = Large;
			math`Couleur[pt]=color;
			AppendTo[pts,math`Graphe[pt]];
		,
			{i,1,Length[listval]}]],
		{j,1,Length[f[[1]]]}];
		(* tri des couleurs pour avoir le bleu au dessus...*)
		pts=Sort[pts,#1[[1,1]] [[1]] > #2[[1,1]][[1]] &];	
		listeg=Join[listeg,pts];	
	Show[listeg,options,PlotRange->{math`cadrex,math`cadrey},math`OptionsGraphe]
	]

(*      	COMPOSEE DE FONCTIONS         *)


EnonceComposee[{a_, b_, c_}] := StringForm["`` o `` o ``", a, b, c];
Composee[{a_, b_, c_}, x_] := StringForm["``(``(``(x))) = ``(``(``)) = ``(``) \
=  ``", a, b, c, a, b, c[x], a, b@c[x], a@b@c[x]]


(*-----------------------------PRIMITIVES------------------------------ -*)
regles = {a_.*Log[x_] + b_.*Log[y_] -> a*Log[x/y] + (b + a)Log[y]}

reglelog2=(Log[u_] -> Log[Simplify[Abs[u],Element[Global`x, Reals]]])


(*recherche dune primitive*)

Primitive[fct_, x_Symbol] := Block[{f,integrale}, 
	f=traitementf[fct,x];
    integrale = Integrate[f, x, Assumptions -> Element[x, Reals]];
    integrale = integrale /. regles;
	If[FreeQ[f, Log], integrale /. reglelog2, integrale,integrale]
    ]

(*avec une substitution subs = g (x) *) 

Primitive[fct_, x_Symbol, t_Symbol,subs_] := Block[{dx,f, ft, xt, prim}, 
	f=traitementf[fct,x];
	If[!FreeQ[subs, t] && FreeQ[subs,x],
		(*calcul de dx*)
		xt = (x -> subs);
      dx = D[subs, t];
      ft=f*dx /. xt;
      prim = Primitive[ft, t];
      Return[prim /. Solve[subs == x, t][[1]]]
	];
     If[!FreeQ[subs,x] && FreeQ[subs, t],
      (*calcul de dx*)
      (*x (t) = solve (xt == t, x)*)
      xt = Solve[subs == t, x];
      dx = D[x /. xt, t][[1]];
      ft = f*dx /. (xt)[[1]];
      prim = Primitive[ft, t];
	  Return[prim /. t -> subs]
      ];
      Null
      ]
 
	
Format[Integrale[fct_,x_Symbol]]:= Defer[Integrate[fct, x]]
(*StringForm["\!\(\*FormBox[FormBox[\n  RowBox[{\"\[Integral]\", \n   RowBox[{\n    `1`, \n    RowBox[{\"\[DifferentialD]\", \"x\"}]}]}],\n  TraditionalForm],\n TraditionalForm]\)",fct]*)

Format[Integrale[fct_,x_Symbol,t_Symbol,subs_]]:=Defer[Integrate[fct, x]]


  
      
Calcule[Integrale[fct_,x_Symbol]]:=Block[{f},
		f=traitementf[fct,x];
		StringForm["`1` = `2` + k",Integrale[fct,x],Primitive[f,x]]
		]
    
Calcule[Integrale[fct_,x_Symbol,t_Symbol,substitution_]]:=Block[{f},
		f=traitementf[fct,x];
		StringForm["`1` = `2` + k",Integrale[fct,x],Primitive[f,x,t,substitution]]
		]   
      
Calcule[Integrale[fct_,x_Symbol],t_Symbol,substitution_]:=Block[{f},
		f=traitementf[fct,x];
		StringForm["`1` = `2` + k",Integrale[fct,x],Primitive[f,x,t,substitution]]
		]
     

(*integration par parties*)

(*Parties[u_, dv_, x_] := Block[{du, v}, du = D[u, x];
     v = Integrate[dv, x];
      
Print[u*v, "\< - \!\(\[Integral]\)\>", v*du, \*"\"\< \\<\[DifferentialD]x = \\>\>\"", 
      u*v - Integrate[v*du, x]]]
 *)
 (*																INTEGRALES DEFINIES						*)    

Unprotect[Plus] 

Plus/: Plus[k_. Integrale[f_,{x_,a_,b_}],l_. Integrale[g_,{x_,a_,b_}]]:=Integrale[k f+l g,{x,a,b}]
Plus/: Plus[Integrale[f_,{x_,a_,b_}], Integrale[f_,{x_,b_,c_}]]:=Integrale[ f,{x,a,c}]

Protect[Plus]

	
Format[Integrale[fct_,{x_Symbol,a_,b_}]]:= Block[{f},
		f=traitementf[fct,x];
		Defer[Integrate[fct, {x,a,b}]]
	]

Presente[k_. i1_Integrale + l_. i2_Integrale]:=StringForm["`1` = `2`",k i1 + l i2,Calcule[k i1+ l i2]]

Presente[Integrale[fct_,{x_Symbol,a_,b_}]]:= Block[{f,i},
		f=traitementf[fct,x];
		i=Integrale[fct,{x,a,b}];
		StringForm["`1` = `2`",Integrale[fct,{x,a,b}],Calcule[i]]
		]


Calcule[Integrale[fct_,{x_Symbol,a_,b_}]]:= Block[{f,sol},
		f=traitementf[fct,x];
		sol=Integrate[f,{x,a,b},Assumptions -> Element[x, Reals]];
		 sol = sol /. Log[nn_Integer]:> SimplifieLog[nn]
		]



Calcule[k_. i1_Integrale + l_. i2_Integrale]:=k Calcule[i1]+l Calcule[i2]

Calcule[k_ * i1_Integrale]:=k Calcule[i1]

Detail[Integrale[fct_,{x_Symbol,a_,b_}]]:= Block[{f,prim},
		f=traitementf[fct,x];
		prim=Primitive[f,x];
		StringForm["`1` = `2` `3` `4` = `5`",Integrale[fct,{x,a,b}],grandcrochetgauche,Primitive[f,x],Subsuperscript[grandcrochetdroit, a, b],Integrate[f,{x,a,b},Assumptions -> Element[x, Reals]]]
		]


Detail[Integrale[fct_,{x_Symbol,a_,b_}],t_Symbol,subs_]:= Block[{f,prim},
		f=traitementf[fct,x];
		prim=Primitive[f,x,t,subs];
		StringForm["`1` = `2` `3` `4` = `5`",Integrale[fct,{x,a,b}],grandcrochetgauche,prim,Subsuperscript[grandcrochetdroit, a, b],Integrate[f,{x,a,b},Assumptions -> Element[x, Reals]]]
		]


Detail[Integrale[fct_,{x_Symbol,a_,b_}],x_Symbol->t_Symbol,subs_]:= Block[{f,ft,dx,prim,xt,at,bt},
		f=traitementf[fct,x];
			xt = (x -> subs);
 			at=t/.Solve[a==subs,t][[1]];
 			bt=t/.Solve[b==subs,t][[1]];
 			dx=D[subs,t];
 			ft=f dx/.xt;
 			prim=Primitive[ft,t];
			StringForm["`1` = `2` `3` `4` = `5`",Integrale[fct,{x,a,b}],grandcrochetgauche,prim,Subsuperscript[grandcrochetdroit, at, bt],Integrate[f,{x,a,b},Assumptions -> Element[x, Reals]]]		
		] /;FreeQ[subs,x] && !FreeQ[subs,t]
		
		
		
Detail[Integrale[fct_,{x_Symbol,a_,b_}],x_Symbol->t_Symbol,subs_]:= Block[{f,ft,dx,prim,xt,at,bt},
		f=traitementf[fct,x];
			xt = Solve[subs == t, x][[1]];
 		    dx = D[x /. xt, t];
    		ft = f*dx /. (xt);
 			at=subs/.(x->a);
 			bt=subs/.(x->b);
 			prim=Primitive[ft,t];
			StringForm["`1` = `2` `3` `4` = `5`",Integrale[fct,{x,a,b}],grandcrochetgauche,prim,Subsuperscript[grandcrochetdroit, at, bt],Integrate[f,{x,a,b},Assumptions -> Element[x, Reals]]]
		]/;!FreeQ[subs,x] && FreeQ[subs,t]

 
grandcrochetgauche=StyleForm["[",FontSize->24]
 
grandcrochetdroit=StyleForm["]",FontSize->24]
  

(*definition de gaphe dans le mauvais package... :-/ *)



Graphe[Integrale[fct_,{x_Symbol,a_,b_}],rules_:(PlotLabel -> None)]:= Block[{axes,f,gf,gfhachure,primg},
	f=traitementf[fct,x];
	gf=Plot[Tooltip[f,Presente["y",f]],{x,-20,20},PlotRange->{-20,20},PlotStyle->{math`CouleurparDefaut,Thickness[Medium]}];
	gfhachure=Plot[f,{x,a,b},PlotRange->{-20,20},PlotStyle->{math`CouleurparDefaut,Thickness[Tiny]},Filling -> Axis];
	primg={gfhachure[[1]],gf[[1]]};
	axes=True;
	Graphics[primg,rules,math`OptionsGraphe]
	]

Graphe[k_. i1_Integrale + l_. i2_Integrale,rules_:(PlotLabel -> None)]:= Show[Graphe[i1],Graphe[i2],rules]


(*recherche des intersections entre f et g*)
Interfg[f_,g_,x_Symbol]:=Block[{racs,valsinter},
	racs=Racines[f-g,x,0];
	valsinter=Extraitvaleurs[racs,x];
	Sort[Intersection[valsinter,valsinter],Less]	
	]
(* recherche des intersections entre f et g restreinte a un intervalle OUVERT a,b*)
Interfg[f_,g_,{x_Symbol,a_,b_}]:=Block[{racs,valsinter},
	racs=Racines[f-g,x,0];
	valsinter=Extraitvaleurs[racs,x];
	valsinter=Sort[Intersection[valsinter,valsinter],Less]	;
	valsinter=Select[Select[valsinter, # > a &], # < b &]
	]

GrapheAire[f_,g_,{x_Symbol,a_,b_},range_:{math`cadrex,math`cadrey}]:=Block[{i,graphef,grapheg,graphe},
	graphef = Plot[Tooltip[f,Presente["y",f]],{x,-20,20},PlotRange->{-20,20},PlotStyle->{math`CouleurparDefaut,Thickness[Medium]}];
  	grapheg = Plot[Tooltip[g,Presente["y",g]],{x,-20,20},PlotRange->{-20,20},PlotStyle->{Darker[Green],Thickness[Medium]}];
  	graphe = Plot[{f, g}, {x, Max[-20,a],Min[b,20]}, Filling -> {1 -> {2}}];
  	Show[{graphef, grapheg,graphe},PlotRange->range,math`OptionsGraphe]
	]
	
	(*surface proposee sans borne donnee*)
Surface[fct_, gct_, x_Symbol,range_:{math`cadrex,math`cadrey}] := Block[{f,g,racs,valsinter,nbinter, a, b, c, i1,i2,expression,graphe},
	f=traitementf[fct,x];
	g=traitementf[gct,x];
	valsinter=Interfg[f,g,x];
	nbinter=Length[valsinter];	
	
 (*si 1 seul ou pas de point d intersection retour erreur + dessin*)
  	If[Length[valsinter] < 2, Return[Print["et je fais quoi avec ton brol??"];Plot[{f, g}, {x, -5,5}, Filling -> {1 -> {2}}]]];
  
  	a = Min[valsinter];
  	b = Max[valsinter];
	Print[GrapheAire[f,g,{x,a,b},range]];
   (*si 2 points, calcul fonction surface avec bornes fixees*)
   If[nbinter==2,Return[Surface[f,g,{x,{a,b}}]]];
  (*si plus de 3 points d intersection, euhh....!!*)
	If[nbinter>3,Return[Print["+ de 3 points d'intersection... essaie avec des bornes, mon gars!"]]];

  (*nbinter=3 , couper l integrale en deux...*)

    If[nbinter==3,
  		c=valsinter[[2]];
  		Return[Surface[f,g,{x,{a,c,b}}]];
    ]
	]

(*surface donnee avec bornes fixees*)
Surface[fct_, gct_, {x_Symbol,bi_,bs_},range_:{math`cadrex,math`cadrey}] := Block[{f,g,racs,valsinter,nbinter, a, b, c, i1,i2,expression,graphe},
	f=traitementf[fct,x];
	g=traitementf[gct,x];

	valsinter=Interfg[f,g,{x,bi,bs}];
	nbinter=Length[valsinter];	
	
 (*si 1 seul ou pas de point d intersection retour erreur + dessin*)

  	a = bi;
  	b = bs;
	Print[GrapheAire[f,g,{x,a,b},range]];
   (*si 2 points, calcul fonction surface avec bornes fixees*)
   If[nbinter==0,Return[Surface[f,g,{x,{a,b}}]]];
  (*si plus de 3 points d intersection, euhh....!!*)
	If[nbinter>1,Return[Print["+ de 1 point d'intersection... essaie avec d'autres bornes, mon gars!"]]];

  (*nbinter=1 , couper l integrale en deux...*)

    If[nbinter==1,
  		c=valsinter[[1]];
  		Return[Surface[f,g,{x,{a,c,b}}]];
    ]
	]	
	

(*surface entre deux fonctions avec bornes fixees et pas d intersection*)
Surface[fct_, gct_, {x_Symbol,{a_,b_}}] := Block[{f,g,valsinter,diff,surface},
	f=traitementf[fct,x];
	g=traitementf[gct,x];
	valsinter=Interfg[f,g,{x,a,b}];
(*normalement, pas d intersection dans a,b ouvert*)
	If[Length[valsinter]!=0,Return[Print["erreur... il y a une intersection dans l'intervalle donne"]]];
	diff = Difference[f,g,{x,a,b}];
	surface = NIntegrate[diff[[1]], {x, a, b}];
	Print[Detail[Integrale[diff[[1]],{ x, a, b}]]];
	Print["S = ",surface]
	]


(*surface entre deux fonctions avec bornes fixees et pas d intersection*)
Surface[fct_, gct_, {x_Symbol,{a_,c_,b_}}] := Block[{f,g,valsinter,diff,surface,diff1,diff2,i1,i2},
	f=traitementf[fct,x];
	g=traitementf[gct,x];
(*premiere integrale sur a c*)
	diff1 = Difference[f,g,{x,a,c}];
  	i1=Integrale[diff1[[1]],{x,a,c}];
	Print[Detail[i1]];
	
(*deuxieme integrale*)	
	diff2 = Difference[f,g,{x,c,b}];
  	i2=Integrale[diff2[[1]],{x,c,b}];
	Print[Detail[i2]];
	surface = NIntegrate[diff1[[1]], {x, a, c}]+NIntegrate[diff2[[1]], {x, c,b}];
	Print["S = ",Calcule[i1] + Calcule[i2]," = ",surface];
	
	]



(*
(*recherche des points d intersection dans l intervelle propose*)
Surface[fct_, gct_, {x_Symbol,bi_,bs_},range_:{cadrex,cadrey}] := Block[{f,g,valsinter,a,b, surface, expression,graphef,grapheg,graphe,abs=False},
	f=traitementf[fct,x];
	g=traitementf[fct,x];
  	valsinter = Interfg[f,g,{x,bi,bs}];

  If[Length[valsinter]==2,a = x /. valsinter[[1]];
  	b = x /. valsinter[[2]],
  	a=bi;b=bs;abs=True,	a=bi;b=bs;abs=True
   	];
  expression = Difference[f,g,{x,a,b}];
  (*expression=If[abs==True,Abs[f-g],expression,expression];*)
  Print[Detail[Integrale[expression[[1]],{ x, a, b}]]];
  
  GrapheAire[f,g,{x,a,b},range]
  ]
  
(* calcul surface entre les bornes donnees !!*)  

Surface[fct_, gct_,{x_Symbol,{bi_,bs_}},range_:{cadrex,cadrey}] := Block[{f,g,intersections,a,b,c, i1,i2,surface, expression,graphef,grapheg,graphe},
	f=traitementf[fct,x];
	g=traitementf[gct,x];

  a=bi;b=bs;
   	
   	(*PROBLEME SI LES COURBES SE CROISENT!!!*)
   (*si elles ne se croisent pas *)
  expression = Difference[f,g,{x,a,b}];
  If[Head[expression]!=choixdiff,
 	surface = Integrate[expression, {x, a, b}];
  	Print[Detail[Integrale[expression,{ x, a, b}]]],
  	(*si un point d intersection*)
  	c=expression[[3]];
  	i1=Integrale[expression[[1]],{x,a,c}];
  	i2=Integrale[expression[[2]],{x,c,b}];
  	Print[Detail[i1]];
  	Print[Detail[i2]];
  	Print[Calcule[i1] + Calcule[i2]]  	
  	,Return[]
  ];
  GrapheAire[f,g,{x,a,b},range]
  ]
  *)
  
(* entre 3 fonctions juste le dessin...*)
Surface[fct_, gct_, hct_,x_Symbol,range_:{math`cadrex,math`cadrey}] := Block[{f,g,h,racs,interfg,interfh,intergh, a, b, surface, expression,graphef,grapheg,grapheh,graphe},
	f=traitementf[fct,x];
	g=traitementf[gct,x];
	h=traitementf[hct,x];
	graphef = Plot[Tooltip[f,Presente["y",f]],{x,-20,20},PlotRange->{-20,20},PlotStyle->{math`CouleurparDefaut,Thickness[Medium]}];
  	grapheg = Plot[Tooltip[g,Presente["y",g]],{x,-20,20},PlotRange->{-20,20},PlotStyle->{Darker[Green],Thickness[Medium]}];
  	grapheh = Plot[Tooltip[h,Presente["y",h]],{x,-20,20},PlotRange->{-20,20},PlotStyle->{Darker[Red],Thickness[Medium]}];
	(*Show[{Graphe[Ens[Global`y == f, x]], Graphe[Ens[Global`y == g, x]], Graphe[Ens[Global`y == h, x]]}, PlotRange -> {cadrex, cadrey}]*)
	graphe = Plot[{f, g,h}, {x, -5,5}];
	Show[graphe,PlotRange->range,math`OptionsGraphe]
  ]
  
Surface[fct_, gct_, hct_,{x_Symbol,bi_,bs_},range_:{math`cadrex,math`cadrey}] := Block[{f,g,h,racs,interfg,interfh,intergh, inters,a, b, c,graphef,grapheg,grapheh,graphe,i,i1,i2},
	f=traitementf[fct,x];
	g=traitementf[gct,x];
	h=traitementf[hct,x];
	interfg = x/.ToRules[Reduce[Simplify[x>=bi && x<=bs && Reduce[f == g, x, Reals]],x,Reals]];
	interfh = x/.ToRules[Reduce[Simplify[x>=bi && x<=bs && Reduce[f == h, x, Reals]],x,Reals]];
	intergh = x/.ToRules[Reduce[Simplify[x>=bi && x<=bs && Reduce[h == g, x, Reals]],x,Reals]];
	inters=Sort[{interfg,interfh,intergh},Less];
	a=inters[[1]];b=inters[[2]];c=inters[[3]];
	graphef = Plot[Tooltip[f,Presente["y",f]],{x,-20,20},PlotRange->{-20,20},PlotStyle->{math`CouleurparDefaut,Thickness[Medium]}];
  	grapheg = Plot[Tooltip[g,Presente["y",g]],{x,-20,20},PlotRange->{-20,20},PlotStyle->{Darker[Green],Thickness[Medium]}];
  	grapheh = Plot[Tooltip[h,Presente["y",h]],{x,-20,20},PlotRange->{-20,20},PlotStyle->{Darker[Red],Thickness[Medium]}];
	(*Show[{Graphe[Ens[Global`y == f, x]], Graphe[Ens[Global`y == g, x]], Graphe[Ens[Global`y == h, x]]}, PlotRange -> {cadrex, cadrey}]*)
	If[a==interfg && c==interfh,
		i1=Integrale[Difference[f,g,{x,a,b}][[1]],{x,a,b}];
		i2=Integrale[Difference[f,h,{x,b,c}][[1]],{x,b,c}];
		i=Calcule[i1] + Calcule[i2];
		graphe = {Plot[{f, g}, {x,a,b},Filling -> {1 -> {2}}],
		Plot[{f, h}, {x,b,c},Filling -> {1 -> {2}}]}
	];
	If[a==interfg && c==intergh,
		i1=Integrale[Difference[f,g,{x,a,b}][[1]],{x,a,b}];
		i2=Integrale[Difference[g,h,{x,b,c}][[1]],{x,b,c}];
		i=Calcule[i1] + Calcule[i2];
				graphe = {Plot[{f, g}, {x,a,b},Filling -> {1 -> {2}}],
		Plot[{g, h}, {x,b,c},Filling -> {1 -> {2}}]}
	];
	If[a==interfh && c==interfg,
		i1=Integrale[Difference[f,h,{x,a,b}][[1]],{x,a,b}];
		i2=Integrale[Difference[f,g,{x,b,c}][[1]],{x,b,c}];
		i=Calcule[i1] + Calcule[i2];
				graphe = {Plot[{f, h}, {x,a,b},Filling -> {1 -> {2}}],
		Plot[{f,g}, {x,b,c},Filling -> {1 -> {2}}]}
	];
	If[a==interfh && c==intergh,
		i1=Integrale[Difference[f,h,{x,a,b}][[1]],{x,a,b}];
		i2=Integrale[Difference[g,h,{x,b,c}][[1]],{x,b,c}];
		i=Calcule[i1] + Calcule[i2];
				graphe = {Plot[{f, h}, {x,a,b},Filling -> {1 -> {2}}],
		Plot[{g,h}, {x,b,c},Filling -> {1 -> {2}}]}
	];
	If[a==intergh && c==interfg,
		i1=Integrale[Difference[g,h,{x,a,b}][[1]],{x,a,b}];
		i2=Integrale[Difference[f,g,{x,b,c}][[1]],{x,b,c}];
		i=Calcule[i1] + Calcule[i2];
				graphe = {Plot[{g, h}, {x,a,b},Filling -> {1 -> {2}}],
		Plot[{f,g}, {x,b,c},Filling -> {1 -> {2}}]}
	];
	If[a==intergh && c==interfh,
		i1=Integrale[Difference[g,h,{x,a,b}][[1]],{x,a,b}];
		i2=Integrale[Difference[f,h,{x,b,c}][[1]],{x,b,c}];
		i=Calcule[i1] + Calcule[i2];
				graphe = {Plot[{g, h}, {x,a,b},Filling -> {1 -> {2}}],
		Plot[{f,h}, {x,b,c},Filling -> {1 -> {2}}]}
	];
	Print[Detail[i1]];
	Print[Detail[i2]];
	Print["S = ",i];
	Show[{graphef,grapheg,grapheh,graphe},PlotRange->range,math`OptionsGraphe]
  ] 

(*    test pour voir quelle fonction est au dessus.....*)

Difference[f_,g_,{x_Symbol,bi_,bs_}]:=Block[{b,a,m,valsinter,nbinter,c,liste={}},
	valsinter=Interfg[f,g,{x,bi,bs}];
	nbinter=Length[valsinter];
	a=If[bi==-Infinity,-100,bi,bi];
	b=If[bs==Infinity,100,bs,bs];
	If[nbinter==0,
		m=(a+b)/2;
		If[(f/.x->m) > (g/.x->m),Return[{f-g}],Return[{g-f}],Return[Print["Ouch!"]]]
	];
	If[nbinter==1,
		c=valsinter[[1]];
		m=(a+c)/2;
		liste=Append[liste,If[(f/.x->m) > (g/.x->m),f-g,g-f]];
		m=(b+c)/2;
		liste=Append[liste,If[(f/.x->m) > (g/.x->m),f-g,g-f]];
		liste=Append[liste,c];
		
		Return[liste]
	]
	]
(*si un pt d intersection , retourne {f-g,g-f,c}*)



Volume[fct_,{x_Symbol,a_,b_},range_:{math`cadrex,math`cadrey}]:=Block[{racs,f,graphef,grapheg,graphe ,primg},
	f=traitementf[fct,x];
	racs=Racines[f,x,0];
	graphef = Plot[Tooltip[f,Presente["y",f]],{x,-20,20},PlotRange->{-20,20},PlotStyle->{math`CouleurparDefaut,Thickness[Medium]}];
	grapheg = Plot[-f,{x,-20,20},PlotRange->{-20,20},PlotStyle->{math`CouleurparDefaut,Thickness[Medium]}];
	Print[Detail[Integrale[Pi f^2,{x,a,b}]]];
	graphe = Plot[{f, -f}, {x, a, b}, Filling -> {1 -> {2}}];
	primg={grapheg [[1]],graphef[[1]],graphe[[1]]};
	Graphics[primg,PlotRange->range,math`OptionsGraphe]
	]

Volume[fct_, gct_, x_Symbol] := Block[{intersections, a, b, f,g,volume,graphe1,graphe2,graphe3,graphe4,expression},
	f=traitementf[fct,x];
	g=traitementf[gct,x];
  intersections = {ToRules[Reduce[f == g, x, Reals]]};
  If[Length[intersections] != 2,
   Return[Print["et je fais quoi avec ton brol??"];Plot[{f, g}, {x, -5,5}, Filling -> {1 -> {2}}]]];
  a = x /. intersections[[1]];
  b = x /. intersections[[2]];
  expression = 
   If[(f /. x -> (a + b)/2) > (g /. x -> (a + b)/2), f^2 - g^2, g^2 - f^2];
  volume = Integrate[Pi (f^2 - g^2), {x, a, b}];
 Print[Detail[Integrale[Pi (expression), {x, a, b}]]];
  graphe1 = Plot[{f, g}, {x, a, b}, Filling -> {1 -> {2}}];
  graphe2 = Plot[{f, g}, {x, a - 0.5, b + 0.5}, PlotRange -> 5, AspectRatio -> Automatic];
  graphe3 = Plot[{-f, -g}, {x, a, b}, Filling -> {1 -> {2}}];
  graphe4 = Plot[{-f,- g}, {x, a - 0.5, b + 0.5}, PlotRange -> 5, AspectRatio -> Automatic];
  Show[{graphe2, graphe1,graphe3,graphe4},PlotRange->{math`cadrex,math`cadrey}]
  ]

(* vague tentative!! *)

Periode[fct_, x_] := Block[{f, fp, pperiode,p},
  fp = fct /. x -> x + p;
  pperiode = Reduce[fp == fct && p > 0 , p, Reals];
  If[pperiode==False,Return[{}]];
  pperiode = pperiode /. C[u_] -> 0;
  pperiode = pperiode /. Or -> List;
  pperiode = pperiode /. And -> List;
  pperiode = Flatten[pperiode];
  pperiode = Select[pperiode, FreeQ[#, x] &];
  
  pperiode = Sort[Intersection[pperiode, pperiode]];
  	If[pperiode!={},pperiode[[1]],pperiode,pperiode]
  ]

Reciproque[fct_, x_,y_] := Block[{f, r,z},
	f=traitementf[fct,x];
	r=Solve[y==f,x,Reals]/.x->z;
	r=r/.y->x;
	r=r/.z->y;
	y/.r
	]


TableauXY[fct_,{x_,a_,b_,dx_}] := Block[{f,t,table},
	f=traitementf[fct,x];
	table=Table[{t,Valeur[f, x, t]/.regleracine},{t,a,b,dx}];
	table = Join[{{x, Global`y}},table];
	GridBox[table, GridFrame -> True, RowLines -> True, ColumnLines -> True] // DisplayForm
	]


TableauXY[fct_,{x_,liste_}] := Block[{f,t,table},
	f=traitementf[fct,x];
	table=Table[{t,Valeur[f, x, t]/.regleracine},{t,liste}];
	table = Join[{{x, Global`y}},table];
	GridBox[table, GridFrame -> True, RowLines -> True, ColumnLines -> True] // DisplayForm
	]


GrapheXY[fct_,{x_,liste_}] := Block[{f,t,table},
	f=traitementf[fct,x];
	table=Table[{t,Valeur[f, x, t]},{t,liste}];
	Graphics[{PointSize[Medium],Blue,Point[table]}]
	]


GrapheXY[fct_,{x_,a_,b_,dx_}] := Block[{f,t,table},
	f=traitementf[fct,x];
	table=Table[{t,Valeur[f, x, t]},{t,a,b,dx}];
	Graphics[{PointSize[Medium],Blue,Point[table]}]
	]



Graphique[arg_]:=Plot[arg,{Global`x,math`cadrex[[1]],math`cadrey[[1]]},math`OptionsGraphe]









Exercices[ex_, n_Integer] := Do[Print[i, ") ", ex[i]], {i, 1, n}]
Solutions[ex_, n_Integer] := Do[Print[i, ") ", Presente[ex[i]]], {i, 1, n}]
SolutionsenDetail[ex_, n_Integer] := Do[Print[i, ") ", Presente[ex[i]]];limites`Detail[ex[i]], {i, 1, n}]
End[]

EndPackage[]

