struct Serie
    u::Function
    s::Function
end

#constructeur à partir du terme général
function Serie(u)
     s(x,n)=reduce(+,(u(x,k) for k in 0:n))
     return Serie(u,s)
end

#somme de deux séries
Base.:+(S1::Serie, S2::Serie) = Serie((x,n)->S1.u(x,n)+S2.u(x,n))

#produit d'une série par un scalaire
function Base.:*(y::Float64,S::Serie)
    u=S.u
    return Serie((x,n)->y*u(x,n))
end

#produit de convolution
function Base.:*(S1::Serie,S2::Serie)
    u , v = S1.u , S2.u
    w(k,x) = reduce(+,(u(x,j)*v(x,k-j) for j in 0:k))
    z(n,x) = reduce(+,(w(x,k) for k in 0:n))
    return Serie(z)
end
        

fact(n)=reduce(*,1:n) #la fonction factorielle


function v2(x,n)
    return n%2==0 ? x^2n/fact(2n) : -x^2n/fact(2n)
end 


expo=Serie((x,n)->x^n/fact(n))
cosinus=Serie(v2)    
geo=Serie((x,n)->x^n)
println(expo.s(1.0,10))
println(cosinus.s(pi/3,10))
println(geo.s(0.5,20))
G2=geo+geo
println(G2.s(0.5,20))
println(2*geo.s(0.5,20))
E2=expo*expo
println(E2.s(1.,10))