% Author     : C. Pierquet (with help of JF.Burnol)
% licence    : Released under the LaTeX Project Public License v1.3c or later, see http://www.latex-project.org/lppl.txt

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{tkz-grapheur}[2026/03/12 0.30c Des outils en TikZ pour travailler comme avec un grapheur]

%====HISTORIQUE
% v 0.30c  Refonte du fonctionnement avec séparation commandes [en/fr]
% -------  Transformations, Taylor (expérimental)
% -------  Ajout de lois de probabilités (continues + discrètes)
% -------  Outils numériques
% v 0.30b  Nouvelle commande pour dérivée/primitive (expérimental)
% -------  Nuage suites
% -------  Courbes paramétrées, polaires
% -------  Voisinages (expérimental)
% -------  Valeurs interdites (expérimental)
% -------  Coniques (expérimental)
% v 0.30a  Création des nœuds (fenêtre + axes)
% v 0.2.9  Clés [Theme/Milli] pour des couleurs prédéfinies de grilles (à définir dans l'environnement)
% v 0.2.8  Clé [Fleche] pour les axes
% v 0.2.7  Gestion de la taille du graphique
% v 0.2.6  Inégalité linéraire (test)
% v 0.2.5  Interpolation de Lagrange + améliorations 
% v 0.2.4  Clé [StyleTrace] pour dotted/dashed par exemple
% v 0.2.3  Bug with length
% v 0.2.2  Bugfix
% v 0.2.1  Option pour compat mode et pgfplots
% v 0.2.0  Petites commandes en lien avec pgfplots + modification mineure splinecubique (calculs Alt)
% v 0.1.9  Correction d'un bug avec la détermination des unités...
% v 0.1.8  Ajout des courbes d'ECC/FCC + Toile récurrence + Points discontinuité + Histobinom
% v 0.1.7  Méthodes intégrales avec des splines
% v 0.1.6  Asymptote verticale + Monte Carlo + Méthode intégrales (rectangles, etc)
% v 0.1.5  Correction d'un bug avec les valeurs manuelles + Nœud pour une image + [en] version !
% v 0.1.4  Ajout des placements de textes
% v 0.1.3  Régressions, avec xintreg (désactivable)
% v 0.1.2  Max/Min + Droites
% v 0.1.1  Densité loi normale + khi deux + Améliorations diverses
% v 0.1.0  Version initiale [fr]

%====OPTIONS
\newif\if@loadsiunitx \@loadsiunitxtrue
\DeclareOption{nonsiunitx}{\@loadsiunitxfalse}%
\DeclareOption{nosiunitx}{\@loadsiunitxfalse}%

\newif\if@loadtikzbabel \@loadtikzbabeltrue
\DeclareOption{nontikzbabel}{\@loadtikzbabelfalse}%
\DeclareOption{notikzbabel}{\@loadtikzbabelfalse}%

\newif\if@loadxintreg \@loadxintregtrue
\DeclareOption{nonxintreg}{\@loadxintregfalse}%
\DeclareOption{noxintreg}{\@loadxintregfalse}%

\newif\if@loadpgfplots \@loadpgfplotstrue
\DeclareOption{nonpgfplots}{\@loadpgfplotsfalse}%
\DeclareOption{nopgfplots}{\@loadpgfplotsfalse}%

\newif\if@loadcompatgfplots \@loadcompatgfplotsfalse
\DeclareOption{compatgfplots}{\@loadcompatgfplotstrue}%

\newif\if@lngenglish \@lngenglishfalse
\DeclareOption{english}{\@lngenglishtrue}%

\DeclareOption*{}
\ProcessOptions\relax

%====BASE
\RequirePackage{tikz}
\RequirePackage{ifthen}
\if@loadpgfplots
  \RequirePackage{pgfplots}
  \usepgfplotslibrary{fillbetween}
  \if@loadcompatgfplots
    \pgfplotsset{compat=1.18}
  \fi
\fi
\usetikzlibrary{calc,intersections,patterns,patterns.meta,bbox}
\RequirePackage{simplekv}
\RequirePackage{xintexpr}
\RequirePackage{xstring}
\RequirePackage{listofitems}
\if@loadxintreg
  \RequirePackage{xint-regression}
\fi

%====SIUNITX + [en]
\if@loadsiunitx
  \RequirePackage{siunitx}
  \if@lngenglish
    \sisetup{mode=match,propagate-math-font=true,reset-math-version=false,reset-text-family=false,reset-text-series=false,reset-text-shape=false,text-family-to-math=true,text-series-to-math=true}
  \else
    \sisetup{locale=FR,output-decimal-marker={,},mode=match,propagate-math-font=true,reset-math-version=false,reset-text-family=false,reset-text-series=false,reset-text-shape=false,text-family-to-math=true,text-series-to-math=true}%
  \fi
\fi

%====TIKZ.BABEL
\if@loadtikzbabel
  \usetikzlibrary{babel}
\fi

%====STYLES DE BASE (PARTAGÉS - FR)
\tikzset{pflnoeud/.style={}}
\tikzset{pflpoint/.style={line width=0.95pt}}
\tikzset{pflpointmc/.style={radius=0.875pt}}
\tikzset{pflpointc/.style={radius=1.75pt}}
\tikzset{pflpointnuage/.style={radius=1.75pt}}
\tikzset{pflcadre/.style={line width=0.8pt,gray}}
\tikzset{pflcourbe/.style={line width=1.05pt}}
\tikzset{pflcourbediscont/.style={line width=1.1pt}}
\tikzset{pfltrait/.style={line width=0.8pt}}
\tikzset{pflbarresprobas/.style={line width=1.5pt}}
\tikzset{pflflecheg/.style={<-,>=latex}}
\tikzset{pflfleched/.style={->,>=latex}}
\tikzset{pflflechegd/.style={<->,>=latex}}
\tikzset{pfltraitvoisinage/.style={line width=0.75pt}}
\tikzset{pfltraitvoisinageasympt/.style={densely dashed,line width=0.75pt}}
\tikzset{pfltraitantec/.style={line width=0.9pt,densely dashed}}
\tikzset{pfltraitimg/.style={line width=0.9pt,densely dashed,->,>=latex}}
\tikzset{pflgrillep/.style={thin,lightgray}}
\tikzset{pflgrillei/.style={line width=0.3pt,lightgray}}
\tikzset{pflgrilles/.style={very thin,lightgray}}
\tikzset{pflaxes/.style={line width=0.8pt,->,>=latex}}
\tikzset{pflaxessansfleche/.style={line width=0.8pt}}
\tikzset{pfltraitsparamecc/.style={line width=0.9pt,densely dashed}}
\tikzset{pflcourbeecc/.style={line width=1.05pt}}
\tikzset{pfltraitrec/.style={line width=0.8pt}}
\tikzset{pfltraitrecpointill/.style={pfltraitrec,densely dashed}}
\tikzset{
  Xmin/.store in=\pflxmin,Xmin/.default=-3,Xmin=-3,
  Xmax/.store in=\pflxmax,Xmax/.default=3,Xmax=3,
  Ymin/.store in=\pflymin,Ymin/.default=-3,Ymin=-3,
  Ymax/.store in=\pflymax,Ymax/.default=3,Ymax=3,
  Origx/.store in=\pflOx,Origx/.default=0,Origx=0,
  Origy/.store in=\pflOy,Origy/.default=0,Origy=0,
  Xgrille/.store in=\pflgrillex,Xgrille/.default=1,Xgrille=1,
  Xgrillei/.store in=\pflgrillexi,Xgrillei/.default=1,Xgrillei=1,
  Xgrilles/.store in=\pflgrillexs,Xgrilles/.default=0.5,Xgrilles=0.5,
  Ygrille/.store in=\pflgrilley,Ygrille/.default=1,Ygrille=1,
  Ygrillei/.store in=\pflgrilleyi,Ygrillei/.default=1,Ygrillei=1,
  Ygrilles/.store in=\pflgrilleys,Ygrilles/.default=0.5,Ygrilles=0.5,
  Rmax/.store in=\pflpolrayonmax,Rmax/.default=3,Rmax=3,
  Rgrille/.store in=\pflpolgrid,Rgrille/.default=1,Rgrille=1,
  Rgrilles/.store in=\pflpolgrids,Rgrilles/.default=0.5,Rgrilles=0.5,
  Tgrille/.store in=\pflgrillet,Tgrille/.default=45,Tgrille=45,
  Tgrilles/.store in=\pflgrillets,Tgrilles/.default=15,Tgrilles=15,
}
\tikzset{%
  pics/pflptcroix/.style args={#1/#2}{
    code={
      \draw[pflpoint,rotate=#2] (-#1,0) -- (#1,0);
      \draw[pflpoint,rotate=#2] (0,-#1) -- (0, #1);
    }
    },
  pics/pflptcroix/.default={2pt/45}
}
\tikzset{%
  pics/pflptcarre/.style args={#1/#2}{
    code={
      \filldraw[draw=none,pflpoint,rotate=#2] (-#1,-#1) rectangle (#1,#1) ;
    }
  },
  pics/pflptcarre/.default={2pt/0}
}

%====STYLES DE BASE (EN)
\tikzset{tkzgrphnode/.style={}}
\tikzset{tkzgrphpoint/.style={line width=0.95pt}}
\tikzset{tkzgrphpointc/.style={radius=1.75pt}}
\tikzset{tkzgrphpointmc/.style={radius=0.875pt}}
\tikzset{tkzgrphscatter/.style={radius=1.75pt}}
\tikzset{tkzgrphframe/.style={line width=0.8pt,gray}}
\tikzset{tkzgrphcurve/.style={line width=1.05pt}}
\tikzset{tkzgrphline/.style={line width=0.8pt}}
\tikzset{tkzgrpharrowl/.style={<-,>=latex}}
\tikzset{tkzgrpharrowr/.style={->,>=latex}}
\tikzset{tkzgrpharrowlr/.style={<->,>=latex}}
\tikzset{tkzgrphcounterimage/.style={line width=0.9pt,densely dashed}}
\tikzset{tkzgrphrange/.style={line width=0.9pt,densely dashed,->,>=latex}}
\tikzset{tkzgrphgridp/.style={thin,lightgray}}
\tikzset{tkzgrphgrids/.style={very thin,lightgray}}
\tikzset{tkzgrphgridi/.style={line width=0.3pt,lightgray}}
\tikzset{tkzgrphaxes/.style={line width=0.8pt,->,>=latex}}
\tikzset{tkzgrphaxeswoarrows/.style={line width=0.8pt}}
\tikzset{
  Xgrid/.store in=\pflgrillex,Xgrid/.default=1,Xgrid=1,
  Xgrids/.store in=\pflgrillexs,Xgrids/.default=0.5,Xgrids=0.5,
  Ygrid/.store in=\pflgrilley,Ygrid/.default=1,Ygrid=1,
  Ygrids/.store in=\pflgrilleys,Ygrids/.default=0.5,Ygrids=0.5,
  Rgrid/.store in=\pflpolgrid,Rgrid/.default=1,Rgrid=1,
  Rgrids/.store in=\pflpolgrids,Rgrids/.default=0.5,Rgrids=0.5,
  Tgrid/.store in=\pflgrillet,Tgrid/.default=45,Tgrid=45,
  Tgrids/.store in=\pflgrillets,Tgrids/.default=15,Tgrids=15,
}
\tikzset{%
  pics/tkzgraphcross/.style args={#1/#2}{
    code={
      \draw[tkzgrphpoint,rotate=#2] (-#1,0) -- (#1,0);
      \draw[tkzgrphpoint,rotate=#2] (0,-#1) -- (0, #1);
    }
    },
  pics/tkzgraphcross/.default={2pt/45}
}
\tikzset{%
  pics/tkzgraphsquare/.style args={#1/#2}{
    code={
      \filldraw[draw=none,tkzgrphpoint,rotate=#2] (-#1,-#1) rectangle (#1,#1) ;
    }
  },
  pics/tkzgraphsquare/.default={2pt/0}
}

%====COULEURS
\definecolor{pflgrillepdefault}{HTML}{f39c12}
\definecolor{pflgrilleidefault}{HTML}{bdc3c7}
\definecolor{pflgrillesdefault}{HTML}{e0e0e0}
\definecolor{pflgrillepgray}{HTML}{707070}
\definecolor{pflgrilleigray}{HTML}{bdc3c7}
\definecolor{pflgrillesgray}{HTML}{f0f0f0}
\definecolor{pflgrillepblue}{HTML}{1565c0}
\definecolor{pflgrilleiblue}{HTML}{90caf9}
\definecolor{pflgrillesblue}{HTML}{e3f2fd}
\definecolor{pflgrillepwarm}{HTML}{d84315}
\definecolor{pflgrilleiwarm}{HTML}{ffab91}
\definecolor{pflgrilleswarm}{HTML}{fbe9e7}
\definecolor{pflgrillepgreen}{HTML}{2e7d32}
\definecolor{pflgrilleigreen}{HTML}{a5d6a7}
\definecolor{pflgrillesgreen}{HTML}{e8f5e9}
\definecolor{pflgrillepcontrast}{HTML}{000000}
\definecolor{pflgrilleicontrast}{HTML}{999999}
\definecolor{pflgrillescontrast}{HTML}{cccccc}

%====CONSTANTE PI pour xint, à voir si incompatibilité...
\xintdefvar pi:=3.141592653589793238462643;
\xintdeffloatvar pi:=3.141592653589793238462643;

%====focntion ln, en langage xint
\xintdeffunc ln(x) := log(x);
\xintdeffloatfunc ln(x) := log(x);

%====Longueurs utiles
\newlength\pflglobalwidth
\newlength\pflglobalheight
\newlength\pflthickgrad

\setlength\pflthickgrad{3pt}

%====DENSITÉ KHIDEUX
\xintdeffloatfunc pflrecigamma(x) := x+0.577215664901*x^2-0.65587807152056*x^3-0.042002635033944*x^4+0.16653861138228*x^5-0.042197734555571*x^6;
\xintdeffloatfunc pflgamma(x) := (x==1)?{1}{(abs(x)<=0.5)?{1/pflrecigamma(x)}{(x-1)*pflgamma(x-1)}};
\xintdeffloatfunc pflkhideux(x,k) := (x<0)?{0}{(1/(2^(k/2)*pflgamma(k/2)))*x^(k/2-1)*exp(-x/2)};

%====PGFPLOTS MACROS (EN/FR)
\NewDocumentCommand\findintersectionspgf{ O{ITSC} m m D<>{\myt} }{%
  %1 = name of node name
  %2 = 1st object
  %3 = 2d object
  %4 = macro storing number of intersections
  \path[name intersections={of=#2 and #3,name=#1,total=\t}] \pgfextra{\xdef#4{\t}} ;
}

\NewDocumentCommand\gextractxnodepgf{ m O{\myxcoord} }{%
  \path \pgfextra{\pgfplotspointgetcoordinates{#1}\pgfkeysgetvalue{/data point/x}{\tmpxgetvalue}\xdef#2{\tmpxgetvalue}} ;
}

\NewDocumentCommand\gextractynodepgf{ m O{\myycoord} }{%
  \path \pgfextra{\pgfplotspointgetcoordinates{#1}\pgfkeysgetvalue{/data point/y}{\tmpygetvalue}\xdef#2{\tmpygetvalue}} ;
}

\NewDocumentCommand\gextractxynodepgf{  m O{\myxcoord} O{\myycoord} }{%
  \path \pgfextra{\pgfplotspointgetcoordinates{#1}\pgfkeysgetvalue{/data point/x}{\tmpxgetvalue}\xdef#2{\tmpxgetvalue}\pgfkeysgetvalue{/data point/y}{\tmpygetvalue}\xdef#3{\tmpygetvalue}} ;
}

\NewDocumentCommand\fillbetweencurvespgf{ O{gray,fill opacity=0.25} m m D<>{} }{%
  \addplot[#1] fill between [of=#2 and #3,soft clip={#4}];
}

\NewDocumentCommand\gensplinecubicpgf{ s m m O{\monspline} }{%
  %1=liste
  \setsepchar[.]{§./}%
  \readlist*\SPLlistepoints{#2}%
  %les données
  \def\tmpsplinenumdeb{1}
  \def\tmpsplinenumfin{\SPLlistepointslen}%
  \pflextractcoeff{#3}{\tmpsplinenumdeb}%
  %nb de calculs
  \def\SPLnbsplines{\inteval{\tmpsplinenumfin-1}}%
  %extraction des coordonnées
  \itemtomacro\SPLlistepoints[\tmpsplinenumdeb,1]\xa%
  \itemtomacro\SPLlistepoints[\tmpsplinenumdeb,2]\ya%
  \itemtomacro\SPLlistepoints[\tmpsplinenumdeb,3]\fprimea%
  \itemtomacro\SPLlistepoints[\tmpsplinenumdeb,1]\xb%
  \itemtomacro\SPLlistepoints[\tmpsplinenumdeb,2]\yb%
  \itemtomacro\SPLlistepoints[\tmpsplinenumdeb,3]\fprimeb%
  \IfBooleanTF{#1}%
    {%
      \xdef\tmpcontrolsxa{\xintfloateval{(\xa)+((\xb)-(\xa))/\COEFFA}}%
      \xdef\tmpcontrolsya{\xintfloateval{(\ya)+(\fprimea)*((\xb)-(\xa))/\COEFFA}}%
      \xdef\tmpcontrolsxb{\xintfloateval{(\xb)-((\xb)-(\xa))/\COEFFA}}%
      \xdef\tmpcontrolsyb{\xintfloateval{(\yb)-(\fprimeb)*((\xb)-(\xa))/\COEFFA}}%
    }%
    {%
      \xdef\tmpcontrolsxa{\xintfloateval{(\xa)+cos(atand(\fprimea))*(\xb-(\xa))/\COEFFA}}%
      \xdef\tmpcontrolsya{\xintfloateval{(\ya)+sin(atand(\fprimea))*(\xb-(\xa))/\COEFFA}}%
      \xdef\tmpcontrolsxb{\xintfloateval{(\xb)-cos(atand(\fprimeb))*(\xb-(\xa))/\COEFFA}}%
      \xdef\tmpcontrolsyb{\xintfloateval{(\yb)-sin(atand(\fprimeb))*(\xb-(\xa))/\COEFFA}}%
    }%
  \xdef#4{(\xa,\ya) ..controls (\tmpcontrolsxa,\tmpcontrolsya) and (\tmpcontrolsxb,\tmpcontrolsyb).. (\xb,\yb)}%
  \foreach \i in {\tmpsplinenumdeb,...,\SPLnbsplines}{%
    %extraction des coeffs de compensation
    \pflextractcoeff{#3}{\i}%
    \def\j{\inteval{\i+1}}%
    \itemtomacro\SPLlistepoints[\i,1]\xa%
    \itemtomacro\SPLlistepoints[\i,2]\ya%
    \itemtomacro\SPLlistepoints[\i,3]\fprimea%
    \itemtomacro\SPLlistepoints[\j,1]\xb%
    \itemtomacro\SPLlistepoints[\j,2]\yb%
    \itemtomacro\SPLlistepoints[\j,3]\fprimeb%
    \IfBooleanTF{#1}%
      {%
        \xdef\tmpcontrolsxa{\xintfloateval{(\xa)+(\xb-(\xa))/\COEFFA}}%
        \xdef\tmpcontrolsya{\xintfloateval{(\ya)+(\fprimea)*(\xb-(\xa))/\COEFFA}}%
        \xdef\tmpcontrolsxb{\xintfloateval{(\xb)-(\xb-(\xa))/\COEFFA}}%
        \xdef\tmpcontrolsyb{\xintfloateval{(\yb)-(\fprimeb)*(\xb-(\xa))/\COEFFA}}%
      }%
      {%
        \xdef\tmpcontrolsxa{\xintfloateval{(\xa)+cos(atand(\fprimea))*(\xb-(\xa))/\COEFFA}}%
        \xdef\tmpcontrolsya{\xintfloateval{(\ya)+sin(atand(\fprimea))*(\xb-(\xa))/\COEFFA}}%
        \xdef\tmpcontrolsxb{\xintfloateval{(\xb)-cos(atand(\fprimeb))*(\xb-(\xa))/\COEFFA}}%
        \xdef\tmpcontrolsyb{\xintfloateval{(\yb)-sin(atand(\fprimeb))*(\xb-(\xa))/\COEFFA}}%
      }%
    \xdef#4{#4 ..controls (\tmpcontrolsxa,\tmpcontrolsya) and (\tmpcontrolsxb,\tmpcontrolsyb).. (\xb,\yb)}%
  }%
}

\NewDocumentCommand\addplotspline{ s O{} D<>{3} m O{\monspline} }{%
  \IfBooleanTF{#1}%
    {%
      \gensplinecubicpgf*{#4}{#3}[#5]%
    }%
    {%
      \gensplinecubicpgf{#4}{#3}[#5]%
    }%
  \draw[#2] #5 ;
}

%====MACRO INTERNE : transformation d'une liste interpo (x1,y1)(x2,y2)... liste reconstruite est stockée dans \TRFlistedecaleeinterpo
\NewDocumentCommand\tkzg@transfo@interpo{ m m m }{%
  %#1=liste interpo originale, #2=a, #3=b
  %retrait de la première '(' et de la dernière ')'
  \StrGobbleLeft{#1}{1}[\TRFtmpinterpo]%
  \StrGobbleRight{\TRFtmpinterpo}{1}[\TRFtmpinterpo]%
  \setsepchar{)(}%
  \readlist*\TRFlisteinterpo{\TRFtmpinterpo}%
  \gdef\TRFlistedecaleeinterpo{}%
  \foreach \i in {1,...,\TRFlisteinterpolen}{%
    \StrCut{\TRFlisteinterpo[\i]}{,}{\TRFxi}{\TRFyi}%
    \xdef\TRFxip{\xintfloateval{(\TRFxi)+(#2)}}%
    \xdef\TRFyip{\xintfloateval{(\TRFyi)+(#3)}}%
    \xdef\TRFlistedecaleeinterpo{\TRFlistedecaleeinterpo(\TRFxip,\TRFyip)}%
  }%
}

%====MACRO INTERNE : transformation d'une liste spline x/y/d § x/y/d §... liste reconstruite est stockée dans \TRFlistedecaleespline
%   NB : pas de § final (cohérent avec le format attendu par \GenererSpline)
\NewDocumentCommand\tkzg@transfo@spline{ m m m }{%
  %#1=liste spline originale, #2=a, #3=b
  \setsepchar[.]{§./}%
  \readlist*\TRFlistepoints{#1}%
  \gdef\TRFlistedecaleespline{}%
  \foreach \i in {1,...,\TRFlistepointslen}{%
    \itemtomacro\TRFlistepoints[\i,1]\TRFxi%
    \itemtomacro\TRFlistepoints[\i,2]\TRFyi%
    \itemtomacro\TRFlistepoints[\i,3]\TRFdi%
    % x' = xi+a,  y' = yi+b,  d' = di (pente inchangée par translation)
    \xdef\TRFxip{\xintfloateval{(\TRFxi)+(#2)}}%
    \xdef\TRFyip{\xintfloateval{(\TRFyi)+(#3)}}%
    % § entre les points, mais pas après le dernier
    \ifnum\i=\TRFlistepointslen%
    \xdef\TRFlistedecaleespline{\TRFlistedecaleespline\TRFxip/\TRFyip/\TRFdi}%
    \else%
    \xdef\TRFlistedecaleespline{\TRFlistedecaleespline\TRFxip/\TRFyip/\TRFdi §}%
    \fi%
  }%
}

%====MACRO INTERNE : réflexion d'une liste interpo (x1,y1)(x2,y2)...
%   stocke le résultat dans \RFXlistedecaleeinterpo
\NewDocumentCommand\tkzg@reflexion@interpo{ m m }{%
  %#1=liste interpo originale, #2=axe (x/y/yx)
  \StrGobbleLeft{#1}{1}[\RFXtmpinterpo]%
  \StrGobbleRight{\RFXtmpinterpo}{1}[\RFXtmpinterpo]%
  \setsepchar{)(}%
  \readlist*\RFXlisteinterpo{\RFXtmpinterpo}%
  \gdef\RFXlistedecaleeinterpo{}%
  \foreach \i in {1,...,\RFXlisteinterpolen}{%
    \StrCut{\RFXlisteinterpo[\i]}{,}{\RFXxi}{\RFXyi}%
    \IfStrEqCase{#2}{%
      {x}{%
        % -f(x) : (xi, -yi)
        \xdef\RFXxip{\xintfloateval{(\RFXxi)}}%
        \xdef\RFXyip{\xintfloateval{-(\RFXyi)}}%
      }%
      {y}{%
        % f(-x) : (-xi, yi)
        \xdef\RFXxip{\xintfloateval{-(\RFXxi)}}%
        \xdef\RFXyip{\xintfloateval{(\RFXyi)}}%
      }%
      {yx}{%
        % réciproque : (yi, xi)
        \xdef\RFXxip{\xintfloateval{(\RFXyi)}}%
        \xdef\RFXyip{\xintfloateval{(\RFXxi)}}%
      }%
    }%
    \xdef\RFXlistedecaleeinterpo{\RFXlistedecaleeinterpo(\RFXxip,\RFXyip)}%
  }%
}

%====MACRO INTERNE : réflexion d'une liste spline x/y/d § x/y/d §... résultat dans \RFXlistedecaleespline
\NewDocumentCommand\tkzg@reflexion@spline{ m m }{%
  %#1=liste spline originale, #2=axe (x/y/yx)
  \setsepchar[.]{§./}%
  \readlist*\RFXlistepoints{#1}%
  \gdef\RFXlistedecaleespline{}%
  % Détermination du sens de parcours :
  %   Axe=x  : abscisses xi inchangées → ordre naturel
  %   Axe=y  : nouvelles abscisses = -xi → ordre inversé si xi croissants
  %   Axe=yx : scope avec matrix transform
  \IfStrEqCase{#2}{%
    {x}{\edef\RFXboucle{1,...,\RFXlistepointslen}\edef\RFXdernierindex{\RFXlistepointslen}}%
    {y}{%
      % nouvelles abscisses = -xi : si xi croissants → -xi décroissants → inverser
      \itemtomacro\RFXlistepoints[1,1]\RFXxpremier%
      \itemtomacro\RFXlistepoints[\RFXlistepointslen,1]\RFXxdernier%
      \xintifboolexpr{(\RFXxpremier) < (\RFXxdernier)}%
      {\edef\RFXboucle{\RFXlistepointslen,...,1}\def\RFXdernierindex{1}}%
      {\edef\RFXboucle{1,...,\RFXlistepointslen}\edef\RFXdernierindex{\RFXlistepointslen}}%
    }%
  }%
  \foreach \i in \RFXboucle{%
    \itemtomacro\RFXlistepoints[\i,1]\RFXxi%
    \itemtomacro\RFXlistepoints[\i,2]\RFXyi%
    \itemtomacro\RFXlistepoints[\i,3]\RFXdi%
    \IfStrEqCase{#2}{%
      {x}{%
        % -f(x) : (xi, -yi, -di)
        \xdef\RFXxip{\xintfloateval{(\RFXxi)}}%
        \xdef\RFXyip{\xintfloateval{-(\RFXyi)}}%
        \xdef\RFXdip{\xintfloateval{-(\RFXdi)}}%
      }%
      {y}{%
        % f(-x) : (-xi, yi, -di)
        \xdef\RFXxip{\xintfloateval{-(\RFXxi)}}%
        \xdef\RFXyip{\xintfloateval{(\RFXyi)}}%
        \xdef\RFXdip{\xintfloateval{-(\RFXdi)}}%
      }%
    }%
    % § entre les points, mais pas après le dernier
    \ifnum\i=\RFXdernierindex\relax%
      \xdef\RFXlistedecaleespline{\RFXlistedecaleespline\RFXxip/\RFXyip/\RFXdip}%
    \else%
      \xdef\RFXlistedecaleespline{\RFXlistedecaleespline\RFXxip/\RFXyip/\RFXdip §}%
    \fi%
  }%
}

%====MACRO INTERNE : calcul de f^(k)(a) par différences finies centrées
%   résultat stocké dans \pfltaylorderivk
%   #1 = nom de la fonction xint
%   #2 = ordre k
%   #3 = point a
%   #4 = pas h
\NewDocumentCommand\tkzg@taylor@derive{ m m m m }{%
  \xdef\pfltaylorderivk{%
    \xintfloateval{%
      add(
      (-1)^(j) * binomial(#2,j) * #1((#3) + ((#2)/2 - j)*(#4)),
      j=0..#2
      ) / (#4)^(#2)
    }%
  }%
}

%====MACRO INTERNE : construction de la fonction Taylor d'ordre N
%   définit pfltaylorpoly(x) comme fonction xint
%   #1 = nom de la fonction xint
%   #2 = ordre N
%   #3 = point a
%   #4 = pas h
\NewDocumentCommand\tkzg@taylor@build{ m m m m }{%
  % calcul des coefficients c_k = f^(k)(a) / k!
  % et construction de la somme
  \gdef\pfltaylorexpr{0}%
  \foreach \k in {0,...,#2}{%
    \tkzg@taylor@derive{#1}{\k}{#3}{#4}%
    % terme k : c_k * (x-a)^k
    \xdef\pfltaylorexpr{%
      \pfltaylorexpr + \pfltaylorderivk / factorial (\k) * (x-(#3))^\k%
    }%
  }%
  \xintdeffloatfunc pfltaylorpoly(x) := \pfltaylorexpr ;%
}

%====INPUT fr
\input{tkz-grapheur-fr.tex}

%====INPUT en
\input{tkz-grapheur-en.tex}

%====INPUT calculs
\input{tkz-grapheur-calc.tex}

\endinput