\section{Computations on Lists}

\subsection{concat}

The function \cmd{ld.concat(table1, table2, \ldots)} concatenates all the tables passed as arguments and returns the resulting table.

\begin{itemize}
    \item Each argument can be a real number, a complex number, or a table.
    \item Example: The instruction \code{ld.concat(1,2,3,{4,5,6},7)} returns the table \val{\{1,2,3,4,5,6,7\}}.
\end{itemize}

\subsection{cut}

The function \cmd{ld.cut(L, A \fac{, before})} cuts \argu{L} at the point \argu{A}, which is assumed to be located on the line \argu{L} (which is either a list of complex numbers or a polygonal line, i.e., a list of lists of complex numbers). If the argument \argu{before} is \false (the default value), then the function returns the part before \argu{A}, followed by the part after \argu{A}; otherwise, the reverse is true.

\subsection{cutpolyline}

The function \cmd{ld.cutpolyline(L, D \fac{, close})} cuts the polygonal line \argu{L} with the straight line \argu{D}. The argument \argu{L} must be a list of complex numbers or a list of lists of complex numbers, the argument \argu{D} is a list of the form \code{\{A,u\}} where $A$ is a complex (point on the line) and $u$ is a non-zero complex (direction vector of the line). The argument \argu{close} indicates whether the line \argu{L} should be closed (\false by default). The function returns three things:
\begin{itemize}
    \item The part of \argu{L} that is in the half-plane defined by the line to the "left" of $u$ (i.e., containing the point $A+iu$) (it is a polygonal line),
    \item followed by the part of \argu{L} that is in the other half-plane (polygonal line),
    \item followed by the list of intersection points between \argu{L} and the line \argu{D}.
\end{itemize}

\begin{demo}{Illustrate a linear programming exercise}
\begin{luadraw}{name=cutpolyline}
local ld = luadraw
local g = ld.graph:new{window={-5,5,-5,5}, size={10,10},margin={0,0,0,0}}
g:Linewidth(6)
local i = ld.cpx.I
local P = g:Box2d() -- polygon representing the 2D window
local D1, D2, D3 = {0,1+i}, {2.5,-i}, {-3*i,-1-i/4} -- trois droites
local P1 = ld.cutpolyline(P,D1,true)
local P2 = ld.cutpolyline(P,D2,true)
local P3 = ld.cutpolyline(P,D3,true)
g:Daxes({0,1,1},{grid=true,gridcolor="LightGray",arrows="->",legend={"$x$","$y$"}})
g:Filloptions("horizontal","blue"); g:Dpolyline(P1,true,"draw=none")
g:Filloptions("fdiag","red"); g:Dpolyline(P2,true,"draw=none")
g:Filloptions("bdiag","green"); g:Dpolyline(P3,true,"draw=none")
g:Filloptions("none","black",1)
g:Linewidth(8)
g:Dline(D1,"blue"); g:Dline(D2,"red"); g:Dline(D3,"green")
g:Dlabel(
  "$x-y\\leqslant 0$",-3-3*i,{pos="N",dir={1+i,-1+i},dist=0.1,node_options="fill=white,fill opacity=0.8"},
  "$x-2.5\\geqslant0$", 2.5+i,{dir={-i,1}},
  "$-\\frac{x}{4}+y+3\\leqslant0$", -3-15/4*i,{pos="S",dir={1+i/4,i-1/4}})
g:Show()
\end{luadraw}
\end{demo}

\subsection{cutpolyline2}

The function \cmd{ld.cutpolyline2(P, f, sg, \fac{, close})} cuts the polygon \argu{P} with the graph of the function \argu{f}. The argument \argu{P} must be a list of complex numbers, and the argument \argu{f} is a function \argu{f}$\colon x \mapsto f(x)\in \mathbf R$. The argument \argu{sg} is either \val{">"} or \val{"<"}. In the first case, the function returns the subset of the polygon \argu{P} whose points satisfy $y>f(x)$, and in the second case, it returns the points satisfying $y<f(x)$. The optional argument \argu{close} indicates whether \argu{P} should be closed.

\begin{demo}{cutpolyline2}
\begin{luadraw}{name=cupolyline2}
local ld = luadraw
local g = ld.graph:new{window = {-4, 4, -4, 4}, size ={10,10}}
g:Daxes({0,1,1}, {grid=true, arrows="-Stealth", legend={"$x$","$y$"}})
local f = function(x) return 1.5*math.sin(x) end
local P = ld.polyreg(0,3,5) -- pentagone
local L = ld.cutpolyline2(P,f,'<',true) -- partie du polygone située sous la courbe de f
g:Dpolyline(L,true,"draw=none,fill=pink,fill opacity=0.6")
g:Linewidth(12)
g:Dcartesian(f, {draw_options="blue"})
g:Dpolyline(P,true,"red")
g:Show()
\end{luadraw}
\end{demo}

\subsection{getbounds}

\begin{itemize}
    \item The function \cmd{ld.getbounds(L)} returns the bounds \val{xmin,xmax,ymin,ymax} of the polygonal line \argu{L}.
    \item Example: \code{local xmin,xmax,ymin,ymax=ld.getbounds(L)} (where \argu{L} denotes a polygonal line).
\end{itemize}

\subsection{getdot}
The function \cmd{ld.getdot(x, L)} returns the point with abscissa \argu{x} (real between $0$ and $1$) along the connected component \argu{L} (list of complex numbers). The abscissa $0$ corresponds to the first point and the abscissa $1$ to the last. More generally, \argu{x} corresponds to a percentage of the length of \emph{L}.

\subsection{insert}
The function \cmd{ld.insert(table1, table2 \fac{, pos})} inserts the elements of \argu{table2} into \argu{table1} at position \argu{pos}.

\begin{itemize}
    \item The argument \argu{table2} can be a real number, a complex number, or a table.
    \item The argument \argu{table1} must be a variable that designates a table; this will be modified by the function.
    \item If the argument \argu{pos} is \nil, the insertion is performed at the end of \argu{table1}.
    \item Example: If a variable $L$ is equal to \val{\{1,2,6\}}, then after the instruction \code{ld.insert(L,{3,4,5},3)}, the variable $L$ will be equal to \val{\{1,2,3,4,5,6\}}.
\end{itemize}

\subsection{interCC}
The function \cmd{ld.interCC(C1, C2)} returns the intersection of circle \argu{C1} with circle \argu{C2}, where \code{C1=\{O1,r1\}} (circle with center $O_1$ and radius $r_1$), and \code{C2=\{O2,r2\}} (circle with center $O_2$ and radius $r_2$). The function returns a list containing $1$ or $2$ points or the entire circle if the intersection is not empty; otherwise, it returns \nil.


\begin{demo}{Tangents to a circle {O,2} and to an ellipse {O,3,2} from a point}
\begin{luadraw}{name=interCC}
local ld = luadraw
local cpx = ld.cpx
local g = ld.graph:new{window={-10,10,-5,5}, margin={0,0,0,0},size={16,8}}
local i = cpx.I
-- pour le cercle {O,2}
g:Saveattr(); g:Viewport(-10,0,-5,5); g:Coordsystem(-4,6,-5,5)
local O = -1
local C1, I = {O, 2}, 4-i
local C2 = {(O+I)/2,cpx.abs(I-O)/2}
local rep = ld.interCC(C1,C2) -- points of tangency
g:Dcircle(C1,"blue"); g:Dcircle(C2,"dashed")
g:Dhline(I,rep[1],"red"); g:Dhline(I,rep[2],"red") --half-tangents
g:Ddots(rep); g:Ddots({O,I}); g:Dlabel("$I$",I,{pos="SE"},"$O$",O,{pos="W"},
  "tangents to the circle arising from $I$",1-5*i,{pos="N"})
g:Restoreattr()
-- pour l'ellipse (E) : {O,3,2}
g:Saveattr(); g:Viewport(0,10,-5,5); g:Coordsystem(-4,6,-5,5)
local mat = {0,1.5,i} -- This matrix transforms a circle {01,2} into the ellipse (E)
local inv_mat = ld.invmatrix(mat) -- inverse matrix
local O1, I1 = table.unpack( ld.mtransform({O,I},inv_mat) ) -- antecedents of O and I
C1 = {O1, 2}
C2 = {(O1+I1)/2,cpx.abs(I1-O1)/2}
rep = ld.interCC(C1,C2) -- points of tangency (tangents from I1)
g:Composematrix(mat) -- The matrix is applied to find the ellipse; the tangency is preserved.
g:Dcircle(C1,"blue"); g:Dcircle(C2,"dashed")
g:Dhline(I1,rep[1],'red'); g:Dhline(I1,rep[2],"red")
g:Ddots(rep); g:Ddots({O1,I1}); g:Dlabel("$I$",I1,{pos="SE"},"$O$",O1,{pos="W"},
  "tangents to the ellipse arising from $I$",1-5*i,{pos="N"})
g:Restoreattr()
g:Show()
\end{luadraw}
\end{demo}

\subsection{interD}

The function \cmd{ld.interD(d1, d2)} returns the intersection point of the lines \argu{d1} and \argu{d2}. A line is a list of two complex numbers: a point on the line and a direction vector.

\subsection{interDC}

The function \cmd{ld.interDC(d, C)} returns the intersection of the line \argu{d} with the circle \argu{C}, where \code{d=\{A,u\}} (a line passing through $A$ and directed by $u$), and \code{C=\{O,r\}} (a circle with center $O$ and radius $r$). The function returns a list containing $1$ or $2$ points if the intersection is not empty; otherwise, it returns \nil.

\subsection{interDL}

The function \cmd{ld.interDL(d, L)} returns the list of intersection points between the straight line \argu{d} and the polygonal line \argu{L}.

\subsection{interL}

The function \cmd{ld.interL(L1, L2)} returns the list of intersection points of the polygonal lines defined by \argu{L1} and \argu{L2}. These two arguments are two lists of complex numbers or two lists of lists of complex numbers.

\subsection{interP}

The function \cmd{ld.interP(P1, P2)} returns the list of intersection points of the paths defined by \argu{P1} and \argu{P2}. These two arguments are two lists of complex numbers and instructions (see \emph{Dpath} page \pageref{Dpath}).


\subsection{linspace}

The function \cmd{ld.linspace(a, b \fac{, nbdots})} returns a list of \argu{nbdots} equally distributed numbers from \argu{a} to \argu{b}. By default, \argu{nbdots} is $50$.

\subsection{map}

The function \cmd{ld.map(f, list)} applies the function \argu{f} to each element of the \argu{list} and returns the table of results. When a result is \nil, the complex \val{cpx.Jump} is inserted into the list.

\subsection{merge}

The function \cmd{ld.merge(L \fac{, epsilon})} reassembles, if possible, the connected components of \argu{L}, which must be a list of lists of complex numbers. The function returns returns a new polygonal line. Comparisons are made to the nearest \argu{epsilon}, by default we have \argu{epsilon}$=10^{-10}$.

\subsection{polyline2path}

The function \cmd{ld.polyline2path(L)} where \argu{L} is a list of complex numbers or a list of lists of complex numbers, returns \argu{L} as a path (which can be drawn with the \cmd{g:Dpath()} method).

\subsection{range}

The function \cmd{ld.range(a, b \fac{, step})} returns the list of numbers from \argu{a} to \argu{b} with a step equal to \argu{step}, which is $1$ by default.


\subsection{read\_csv\_file}

The function \cmd{ld.read\_csv\_file(file, options)} reads a \emph{csv} file. The argument \argu{file} is a string representing the file with the extension: \code{"<name>.csv"}. The argument \argu{options} is an table whose fields represent the options, which are (with their default values):
\begin{itemize}
    \item \opt{header=true}, with the value \true this means that the first line of the file contains the column names.

    \item \opt{dic=false}, with the value \true this means that the returned result will be a list of dictionaries (one per line), the keys of these dictionaries being the column names. With the value \false (default value), the result is a list of lists of values ​​(one list of values ​​per line). When the \opt{header} option is set to \false, the \opt{dic} option automatically remains \false.

    \item \opt{sep=","}, a string indicating the separator for the values ​​on each line.
    
    \item \opt{num=true}, a boolean indicating whether the values ​​should be automatically converted to numeric values ​​(when this conversion fails, the value remains a string).
    
    \item \opt{comment="\%\%"}, a string announcing a comment (a line starting with these characters is ignored). \textbf{Warning}: the search uses Lua's \emph{match} method, for which the \% character is a special character; it must be doubled ("\%\%") to be considered a character.
\end{itemize}

The result returned by this function is a sequence consisting, in this order, of:
\begin{enumerate}
    \item A list of result lists (one result list per line).
    \item The list of values ​​in the first line when the \opt{header} option is set to \true.
\end{enumerate}


\subsection{Clipping Functions}

\begin{itemize}
    \item The function \cmd{ld.clipseg(A, B, xmin, xmax, ymin, ymax)} clips the segment $[A;B]$ (complex numbrers) with the window $[x_{\mathrm{min}};x_{\mathrm{max}}]\times [y_{\mathrm{min}};y_{\mathrm{max}}]$ and returns the result.

    \item The function \cmd{ld.clipline(d, xmin, xmax, ymin, ymax)} clips the line \argu{d} with the window $[x_{\mathrm{min}};x_{\mathrm{max}}]\times [y_{\mathrm{min}};y_{\mathrm{max}}]$ and returns the result. The line \argu{d} is a list of two complex numbers: a point and a direction vector.

    \item The function \cmd{ld.clippolyline(L, xmin, xmax, ymin, ymax \fac{, close})} clips the polygonal line \argu{L} with the  window $[x_{\mathrm{min}};x_{\mathrm{max}}]\times [y_{\mathrm{min}};y_{\mathrm{max}}]$ and returns the result. The argument \argu{L} is a list of complex numbers or a list of lists of complex numbers. The optional argument \argu{close} (\false by default) indicates whether the polygonal line should be closed.

    \item The function \cmd{ld.clipdots(L, xmin, xmax, ymin, ymax)} clips the point list (complex numbers) \argu{L} with the window $[x_{\mathrm{min}};x_{\mathrm{max}}]\times [y_{\mathrm{min}};y_{\mathrm{max}}]$ and returns the result (exterior points are simply excluded). The argument \argu{L} is a list of complex numbers or a list of lists of complex numbers.
\end{itemize}

\subsection{Adding Mathematical Functions}

In addition to the functions associated with graphics methods that perform calculations and return a polygonal line (such as \cmd{ld.cartesian}, \cmd{ld.periodic}, \cmd{ld.implicit}, \cmd{ld.odesolve}, etc), the \luadrawenv package adds some mathematical functions that are not natively provided in the \emph{math} module.

\subsubsection{Protected Evaluation: evalf}
The \cmd{ld.evalf(f, \ldots)} function allows you to evaluate \code{f(\ldots)} and return the result if there is no runtime error in Lua; otherwise, the function returns \nil. For example, executing:
\begin{Luacode}
local Z = cpx.Z
local f = function(a,b)
    return 2*Z(a,1/b)
end
print(f(1,0))
\end{Luacode}
causes the runtime error \verb|attempt to perform arithmetic on a nil value| (in the console), because here \code{Z(1,1/0)} returns \nil, and Lua does not accept an argument equal to \nil in a calculation. On the other hand, executing:
\begin{Luacode}
local Z = cpx.Z
local f = function(a,b)
    return 2*Z(a,1/b)
end
print(ld.evalf(f,1,0))
\end{Luacode}
does not cause an error from Lua, and there is no output to the console either since the value to be displayed is \nil.

\subsubsection{int}
The function \cmd{ld.int(f, a, b)} returns an approximate value of the integral of the function \argu{f} over the interval $[a;b]$ (two complex numbers). The function \argu{f} is a real variable and has real or complex values. The method used is Simpson's method, accelerated twice with the Romberg method.

\paragraph{Example:}
\begin{TeXcode}
$\int_0^1 e^{t^2}\mathrm d t \approx \directlua{tex.sprint(int(function(t) return math.exp(t^2) end, 0, 1))}$
\end{TeXcode}
\paragraph{Result:} $\int_0^1 e^{t^2}\mathrm d t \approx \directlua{tex.sprint(luadraw.int(function(t) return math.exp(t^2) end, 0, 1))}$.

\subsubsection{gcd}
The function \cmd{ld.gcd(a, b)} returns the greatest common divisor between \argu{a} and \argu{b}, two integers.

\subsubsection{lcm}
The function \cmd{ld.lcm(a, b)} returns the smallest positive common divisor between \argu{a} and \argu{b}, two integers.

\subsubsection{nth\_root}
The function \cmd{ld.nth\_root(n, x)} returns the nth root of the real number \argu{x}, the argument \argu{n} must be an integer.

\subsubsection{solve}
The function \cmd{ld.solve(f, a, b \fac{, n, df})} numerically solves the equation $f(x)=0$ in the interval $[a;b]$, the argument \argu{f} is the function, \argu{a}, \argu{b} are two complex numbers. The interval is subdivided into $n$ pieces ($25$ by default). The interval is subdivided into $n$ pieces ($25$ by default). The optional argument \argu{df} is a function that represents the derivative of \argu{f}; when this argument is absent, an approximation of the derivative is used. The function returns a list of results or \emph{nil}. The method used is a variant of Newton's method. The function returns a list of numbers or \nil.

\paragraph{Example 1:}
\begin{TeXcode}
\begin{luacode}
local ld = luadraw
resol = function(f,a,b) 
    local y = ld.solve(f,a,b) 
    if y == nil then tex.sprint("\\emptyset") 
    else 
        local str = y[1] 
        for k = 2, #y do 
            str = str..", "..y[k] 
        end 
        tex.sprint(str) 
    end
end
\end{luacode}
\def\solve#1#2#3{\directlua{resol(#1,#2,#3)}}%
\begin{luacode}
f1 = function(x) return math.cos(x)-x end
f2 = function(x) return x^3-2*x^2+1/2 end
\end{luacode}
Solving the equation $\cos(x)=x$ in $[0;\frac{\pi}2]$ gives $\solve{f1}{0}{math.pi/2}$.\par
Solving the equation $\cos(x)=x$ in $[\frac{\pi}2;\pi]$ gives $\solve{f1}{math.pi/2}{math.pi}$.\par
Solving the equation $x^3-2x^2+\frac12=0$ in $[-1;2]$ gives: $\{\solve{f2}{-1}{2}\}$.
\end{TeXcode}
\paragraph{Result:}\ \par

\begin{luacode}
local ld = luadraw
resol = function(f,a,b) 
    local y = ld.solve(f,a,b) 
    if y == nil then tex.sprint("\\emptyset") 
    else 
        local str = y[1] 
        for k = 2, #y do 
            str = str..", "..y[k] 
        end 
        tex.sprint(str) 
    end
end
\end{luacode}
\def\solve#1#2#3{\directlua{resol(#1,#2,#3)}}%
\begin{luacode}
f1 = function(x) return math.cos(x)-x end
f2 = function(x) return x^3-2*x^2+1/2 end
\end{luacode}

Solving the equation $\cos(x)=x$ in $[0;\frac{\pi}2]$ gives $\solve{f1}{0}{math.pi/2}$.\par
Solving the equation $\cos(x)=x$ in $[\frac{\pi}2;\pi]$ gives $\solve{f1}{math.pi/2}{math.pi}$.\par
Solving the equation $x^3-2x^2+\frac 12=0$ in $[-1;2]$ gives: $\{\solve{f2}{-1}{2}\}$.

\paragraph{Example 2:} We want to plot the curve of the function $f$ defined by the condition:
\[\forall x\in \mathbf R,\ \int_x^{f(x)} \exp(t^2)\mathrm d t = 1.\]
We have two possible methods:
\begin{enumerate}
    \item We consider the function $G\colon (x,y) \mapsto \int_x^y \exp(t^2)\mathrm d t-1$, and we draw the implicit curve with equation $G(x,y)=0$.
    \item We determine a real number $y_0$ such that $\int_0^{y_0}\exp(t^2)\mathrm d t = 1$ and we draw the solution to the differential equation $y'=e^{x^2-y^2}$ satisfying the initial condition $y(0)=y_0$.
\end{enumerate}
Let's draw both:
\begin{demo}{Function $f$ defined by $\int_x^{f(x)} \exp(t^2)\mathrm d t = 1$.}
\begin{luadraw}{name=int_solve}
local ld = luadraw
local Z = ld.cpx.Z
local g = ld.graph:new{window={-3,3,-3,3},size={10,10}}
local h = function(t) return math.exp(t^2) end
local G = function(x,y) return ld.int(h,x,y)-1 end
local H = function(y) return G(0,y) end
local F = function(x,y) return math.exp(x^2-y^2) end
local y0 = ld.solve(H,0,1)[1] -- solution of H(x)=0
g:Daxes({0,1,1}, {arrows="->"})
g:Dimplicit(G, {draw_options="line width=4.8pt,Pink"})
g:Dodesolve(F,0,y0,{draw_options="line width=0.8pt"})
g:Lineoptions("dashed","gray",4); g:DlineEq(1,-1,0); g:DlineEq(1,1,0) -- bisectors
g:Dlabel("${\\mathcal C}_f$",Z(2.15,2),{pos="S"})
g:Show()
\end{luadraw}
\end{demo}

We see that the two curves overlap well, however the first method (implicit curve) is much more computationally intensive, so method 2 is preferable.
