(*   par Marcel Délèze   *)

BeginPackage["EtudeFct`"]

restreins::usage=
	"restreins[cond] rajoute la condition cond[x] à l'ensemble de définition."

tv::usage=
	"tv[f] donne le tableau de variations de la fonction f."

Ntv::usage=
	"Ntv[f] donne le tableau de variations de la fonction f."

valAbs::usage=
	"valAbs[x] donne la valeur absolue de x."

indicGT::usage=
"indicGT[a][x] est la fonction indicatrice de l'intervalle ]a; ∞[\n(non définie en x=a)."

indicLT::usage=
"indicLT[b][x] est la fonction indicatrice de l'intervalle ]-∞, b[\n(non définie en x=b)."

indicGTLT::usage=
"indicGTLT[a,b][x] est la fonction indicatrice de l'intervalle ]a, b[\n(non définie en x=a et x=b)."

Begin["`Private`"]

<<Tableaux`

Off[General::"spell1"]

Off[Reduce::"ratnz"]

valAbs[t_]=(Sqrt[(t^2)]);

indicGT[a_][t_]=(1/2)+((valAbs[t-a])/(2(t-a)));

indicLT[b_][t_]=(1/2)-((valAbs[t-b])/(2(t-b)));

indicGTLT[a_,b_][t_]=indicGT[a][t]*indicLT[b][t]

ordonne[e_]:=If[Head[e]===Or,Sort[e,(#1[[2]]<#2[[2]])&],e]

simpl[k_]:=Reduce[Simplify[k],x,Reals]

afficheExpr[k_]:=HoldForm[k]/.{True->"x∈ℝ",False->"x∈{}",x->"x"}

restreins[cond_/; Not[Head[cond]===Symbol ∨ Head[cond]===Function]]:=(Print["L'argument de restreins doit être une fonction booléenne, par exemple"];
	Print["cond[x_] = (0≤x≤1);    restreins[cond]"])

restreins[cond_]:=(restriction=cond[x]; afficheExpr[restriction])

afficheSgn[{n_, z_, p_}]:=afficheTableau[{"négatif pour","nul pour", "positif pour"},None,{{afficheExpr[simpl[n]]},{afficheExpr[ordonne[simpl[z]]]},{afficheExpr[simpl[p]]}}]

ensDef[fct_]:=Reduce[restriction∧((fct[x]<0 )∨( fct[x]≥0)), x, Reals]

zeros[fct_]:=Reduce[restriction∧(fct[x]==0),x ,Reals]

valX[e_]:=Simplify[
If[Head[e]===Or,Apply[List,e],e]/.Equal[x,vx_]->vx
];

sgn[fct_]:={Reduce[restriction∧(fct[x]<0),x,Reals],
zeros[fct],
Reduce[restriction∧(fct[x]>0),x,Reals]}

ensDefD1[fct_]:=(ensDef[fct])∧(ensDef[fct']);

ensDefD2[fct_]:=(ensDef[fct])∧(ensDef[fct'])∧(ensDef[fct''])

zerosD1[fct_]:=Reduce[ensDef[fct]∧(fct'[x]==0),x,Reals]

zerosD2[fct_]:=Reduce[ensDefD1[fct]∧(fct''[x]==0),x,Reals]

sgnD1[fct_]:={Reduce[ensDef[fct]∧(fct'[x]<0),x,Reals],
zerosD1[fct],
Reduce[ensDef[fct]∧(fct'[x]>0),x,Reals]}

sgnD2[fct_]:={Reduce[ensDefD1[fct]∧fct''[x]<0,x,Reals],
zerosD2[fct],
Reduce[ensDefD1[fct]∧(fct''[x]>0),x,Reals]}

asAffPlus[fct_]:=  Print["Du côté +∞, fonction non définie."]/;(ensDef[fct]/.x->(10^99))=!=True;

asAffPlus[fct_]:=Module[{a, b,t},a=Limit[((fct[t])/t),t->∞];b=Limit[fct[t]-a*t,t->∞];
If[a===0, If[NumericQ[b],Print["Du côté +∞, asymptote horizontale y= ",b],Print["Du côté +∞, direction asymptotique nulle et f(x)⟶ ",b]],If[NumericQ[a],
If[NumericQ[b],  Print["Du côté +∞, asymptote affine y = (",a,")x +(",b,")"],   Print["Du côté +∞, pas d'asymptote affine (direction asymptotique = ",a,")"]],  Print["Du côté +∞, pas d'asymptote affine."]] ]]

asAffMoins[fct_]:=  Print["Du côté -∞, fonction non définie."]/;(ensDef[fct]/.x->-(10^99))=!=True;

asAffMoins[fct_]:=Module[{a, b,t},a=Limit[((fct[t])/t),t->-∞];b=Limit[fct[t]-a*t,t->-∞];
If[a===0, If[NumericQ[b],Print["Du côté -∞, asymptote horizontale y= ",b],Print["Du côté -∞, direction asymptotique nulle et f(x)⟶ ",b]],If[NumericQ[a],
If[NumericQ[b],  Print["Du côté -∞, asymptote affine y = (",a,")x +(",b,")"],   Print["Du côté -∞, pas d'asymptote affine (direction asymptotique = ",a,")"]],  Print["Du côté -∞, pas d'asymptote affine."] ]]]

NasAffPlus[fct_]:=  Print["Du côté +∞, fonction non définie."]/;(ensDef[fct]/.x->(10^99))=!=True;

NasAffPlus[fct_]:=Module[{a, b,t},a=Limit[((fct[t])/t),t->∞];b=Limit[fct[t]-a*t,t->∞];
If[a===0, If[NumericQ[b],Print["Du côté +∞, asymptote horizontale y= ",N[b]],Print["Du côté +∞, direction asymptotique nulle et f(x)⟶ ",N[b]]],If[NumericQ[a],
If[NumericQ[b],  Print["Du côté +∞, asymptote affine y = (",N[a],")x +(",N[b],")"],   Print["Du côté +∞, pas d'asymptote affine (direction asymptotique = ",N[a],")"]],  Print["Du côté +∞, pas d'asymptote affine."] ]]]

NasAffMoins[fct_]:=  Print["Du côté -∞, fonction non définie."]/;(ensDef[fct]/.x->-(10^99))=!=True;

NasAffMoins[fct_]:=Module[{a, b,t},a=Limit[((fct[t])/t),t->-∞];b=Limit[fct[t]-a*t,t->-∞];
If[a===0, If[NumericQ[b],Print["Du côté -∞, asymptote horizontale y= ",N[b]],Print["Du côté -∞, direction asymptotique nulle et f(x)⟶ ",N[b]]],If[NumericQ[a],
If[NumericQ[b],  Print["Du côté -∞, asymptote affine y = (",N[a],")x +(",N[b],")"],
   Print["Du côté -∞, pas d'asymptote affine (direction asymptotique = ",N[a],")"]],  Print["Du côté -∞, pas d'asymptote affine."] ]]]

extr[fct_]:=Module[{z=zerosD1[fct]},"Aucun"/;z==False]

extr[fct_]:=Module[{z=zerosD1[fct]},{"x∈ℝ", "f(ℝ)"}/;z==True]

extr[fct_]:=Module[{z=valX[zerosD1[fct]]},If[Head[z]===List,
z=Sort[z,LessEqual];Transpose[{z, Simplify[fct[z]]}], 
{{z, fct[z]}}]]

afficheExtr[e_List/;Not[FreeQ[e,x]]∧Length[Dimensions[e]]===1]:=Print["Candidat(s) extremum(s) : ",{ e[[1]],"f(%)"}/.x->"x"]

afficheExtr[e_List/;Not[FreeQ[e,x]]∧Length[Dimensions[e]]===2]:=Print["Candidat(s) extremum(s) : ",Table[{ e[[k,1]],"f(%)"}/.x->"x",{k,1,Length[e]}]]

afficheExtr[e_]:=Print["Candidat(s) extremum(s) : ", e]

pi[fct_]:=Module[{z=zerosD2[fct]},"Aucun"/;z==False]

pi[fct_]:=Module[{z=zerosD2[fct]},{"x∈ℝ", "f(ℝ)"}/;z==True]

pi[fct_]:=Module[{z=valX[zerosD2[fct]]},If[Head[z]===List,
z=Sort[z,LessEqual];Transpose[{z, Simplify[fct[z]]}],
{ {z,fct[z]}}]]

affichePi[e_List/;Not[FreeQ[e,x]]∧Length[Dimensions[e]]===1]:=Print["Candidat(s) point(s) d'inflexion : ",{ e[[1]],"f(%)"}/.x->"x"]

affichePi[e_List/;Not[FreeQ[e,x]]∧Length[Dimensions[e]]===2]:=Print["Candidat(s) points(s) d'inflexion: ",Table[{ e[[k,1]],"f(%)"}/.x->"x",{k,1,Length[e]}]]

affichePi[e_]:=Print["Candidat(s) points(s) d'inflexion : ", e]

tv[fct_]:=(
Print["Ensemble de définition de f : ",afficheExpr[simpl[ensDef[fct]]]];
		Print["f(x) = ",afficheExpr[Factor[fct[x]]]];
		Print["Signe(f(x)) : ",afficheSgn[sgn[fct]]];
                    Print["f'(x) = ",afficheExpr[Factor[fct'[x]]]];
                  Print["Signe(f'(x)) : ", afficheSgn[sgnD1[fct]]];
                  Print["f''(x) = ",afficheExpr[Factor[fct''[x]]]];
                  Print["Signe(f''(x)) : ",  afficheSgn[sgnD2[fct]]];
                 afficheExtr[extr[fct]];
                  affichePi[ pi[fct]];
                 asAffPlus[fct];
                asAffMoins[fct]);

Ntv[fct_]:=(
Print["Ensemble de définition de f : ",afficheExpr[N[simpl[ensDef[fct]]]]];
		Print["f(x) = ",afficheExpr[Factor[N[fct[x]]]]];
		Print["Signe(f(x)) : ",afficheSgn[N[sgn[fct]]]];
                    Print["f'(x) = ",afficheExpr[Factor[N[fct'[x]]]]];
                  Print["Signe(f'(x)) : ", afficheSgn[N[sgnD1[fct]]]];
                  Print["f''(x) = ",afficheExpr[Factor[N[fct''[x]]]]];
                  Print["Signe(f''(x)) : ",  afficheSgn[N[sgnD2[fct]]]];
                  afficheExtr[ N[extr[fct]]];
                 affichePi[ N[pi[fct]]];
                NasAffPlus[fct];
                NasAffMoins[fct]);

On[General::"spell1"]

restriction=True;

End[]

EndPackage[]