-- luadraw_real.lua (chargé par luadraw_complex.lua) -- date 2026/05/29 -- version 3.1 -- Copyright 2026 Patrick Fradin -- This work may be distributed and/or modified under the -- conditions of the LaTeX Project Public License. -- The latest version of this license is in -- https://www.ctan.org/license/lppl local ld = luadraw ld.digits = 4 -- nombre de décimales dans les exports ld.epsilon = 1e-16 ld.mm = math.floor(7227/254) -- conversion en dixième de point, ex: Linewidth(2*mm) pour une épaisseur de 2 millimètres ld.pt = 254/7227 -- conversion en cm, ex : 2*pt pour une longueur en cm équivalente à 2 points ld.deg = math.pi/180 -- conversion en radians, ex 180*deg = pi ld.rad = 180/math.pi -- conversion en degrés, ex : pi*rad = 180 ld.siunitx = false -- utilisé dans la fonction num function ld.strReal(reel,dgt) -- convertit un réel en chaîne avec dgt décimales dgt = dgt or ld.digits local str = string.format("%." ..dgt.."f",reel) local n = #str while string.sub(str,n,n) == "0" do n = n-1 end if string.sub(str,n,n) == "." then n = n-1 end local rep = string.sub(str,1,n) if rep == "-0" then rep = "0" end return rep end function ld.num(x,dgt) -- x is a real, returns a string local rep = ld.strReal(x,dgt) if ld.siunitx then rep = "\\num{"..rep.."}" end --needs \usepackage{siunitx} return rep end function ld.isNaN(reel) -- reel est supposé être un nombre return reel ~= reel end function ld.isInf(reel) -- reel est supposée être un nombre return (reel == math.huge) or (reel == -math.huge) end function ld.notDef(reel) -- reel est supposée être un nombre return (reel==nil) or ld.isNaN(reel) or ld.isInf(reel) end function ld.isNul(reel) return math.abs(reel) < ld.epsilon end function ld.round(num, nbDeci) local mult = 10^(nbDeci or 0) return math.floor(num * mult + 0.5) / mult end function ld.nearest(x) -- nearest integer local a, b = math.floor(x), math.ceil(x) if x <= (a+b)/2 then return a else return b end end function ld.range(a, b, step) step = step or 1 local res = {} for k = a, b, step do table.insert(res,k) end return res end function ld.linspace(a,b,nbdots) local res = {} nbdots = nbdots or 50 local pas = (b-a)/(nbdots-1) local x = a for _ = 1, nbdots do table.insert(res,x) x = x+pas end return res end function ld.reverse(list) local rep = {} for _,x in ipairs(list) do table.insert(rep,1,x) end return rep end function ld.gcd(a,b) a = math.abs(a) b = math.abs(b) local igcd igcd = function(u,v) if v == 0 then return u else return igcd(v, u%v) end end return igcd(a,b) end function ld.lcm(a,b) return math.abs(a*b) // ld.gcd(a,b) end function ld.solve(f,a,b,n,df) -- version 2.4 of luadraw n = n or 25 if a > b then a, b = b, a end local x, delta, S = a, (b-a)/n, {} local fin, h, r = x+delta, 1e-6, nil if df == nil then df = function(x) return (f(x+h)-f(x))/h end end local iter = function(x) return x-f(x)/df(x) end while x < b do r = x+delta/2 for i = 1,5 do if r ~= nil then r = ld.evalf(iter,r) end if (r==nil) then break end end if (r ~= nil) and (r >= x) and (r < fin) and (math.abs(f(r)) < 1e-6) then table.insert(S,r) -- we consider that r is a solution end x = fin; fin = x+delta end if #S > 0 then return S end end function ld.int(f,a,b) -- calcule numériquement l'intégrale de la fonction f de a à b, -- f est une fonction à variable réelle mais peut être à valeurs complexes -- a et b sont deux réels. if (f == nil) or (a == nil) or (type(a) ~= "number") or (b == nil) or (type(b) ~= "number") then return end local h, deuxN, compt = b-a, 1, 0 local M0, M1, S0, S1, U0, U1, V0, V1 local stop, error = false, false local median = function() local x = a+h/2 local r, y = f(x) for k = 1, deuxN-1 do x = x+h; y = f(x) if y ~= nil then r = r+y else error = true; return end end return h*r end S1 = h*(f(a)+f(b)+4*f((a+b)/2))/6 M1 = median(); stop = (M1 == nil) or (S1 == nil) while (not stop) and (compt <= 10) do compt = compt+1; M0 = M1; S0 = S1; U0 = U1; V0 = V1 deuxN = 2*deuxN; h = h/2 M1 = median() if not error then S1 = S0/2+2*M1/3-M0/6; error = (S1 == nil) end if not error then U1 = (16*S1-S0)/15; error = (U1 == nil) end if (not error) and (compt > 1) then V1 = (64*U1-U0)/63; error = (V1 == nil) end stop = error or ( (compt >= 3) and (V0 ~= nil) and (V1 ~= nil) and (ld.cpx.abs(V0-V1) < 1e-6) ) end if not error then return V1 end end function ld.nth_root(n,x) -- n is a positive integer with n>1 -- x is a real if x>=0 then return x^(1/n) elseif n%2 == 1 then return -(-x)^(1/n) end end