Formal power series: Difference between revisions

Added Julia language
(→‎{{header|Kotlin}}: Added preamble, code and output.)
(Added Julia language)
Line 1,091:
=={{header|Java}}==
See [[Formal power series/Java]]
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
 
'''Module''':
<lang julia>module FormalPowerSeries
 
_div(a, b) = a / b
_div(a::Union{Integer,Rational}, b::Union{Integer,Rational}) = a // b
 
abstract type AbstractFPS{T<:Number} end
 
Base.iteratorsize(::AbstractFPS) = Base.IsInfinite()
Base.done(::AbstractFPS, ::Any) = false
Base.iteratoreltype(::AbstractFPS) = Base.HasEltype()
Base.eltype(::AbstractFPS{T}) where T = T
Base.one(::AbstractFPS{T}) where T = ConstantFPS(one(T))
 
function Base.show(io::IO, fps::AbstractFPS{T}) where T
itr = Iterators.take(fps, 8)
s = start(itr)
a, s = next(itr, s)
print(io, a)
a, s = next(itr, s)
@printf(io, " %s %s⋅x",
ifelse(sign(a) ≥ 0, '+', '-'), abs(a))
local i = 2
while !done(itr, s)
a, s = next(itr, s)
@printf(io, " %s %s⋅x^%i",
ifelse(sign(a) ≥ 0, '+', '-'), abs(a), i)
i += 1
end
print(io, "...")
end
 
struct MinusFPS{T,A<:AbstractFPS{T}} <: AbstractFPS{T}
a::A
end
Base.:-(a::AbstractFPS{T}) where T = MinusFPS{T,typeof(a)}(a)
 
Base.start(fps::MinusFPS) = start(fps.a)
function Base.next(fps::MinusFPS, st)
v, s = next(fps.a, st)
return -v, s
end
 
struct SumFPS{T,A<:AbstractFPS,B<:AbstractFPS} <: AbstractFPS{T}
a::A
b::B
end
Base.:+(a::AbstractFPS{A}, b::AbstractFPS{B}) where {A,B} =
SumFPS{promote_type(A, B),typeof(a),typeof(b)}(a, b)
Base.:-(a::AbstractFPS, b::AbstractFPS) = a + (-b)
 
Base.start(fps::SumFPS) = (start(fps.a), start(fps.b))
function Base.next(fps::SumFPS{T,A,B}, st) where {T,A,B}
stateA, stateB = st
valueA, stateA = next(fps.a, stateA)
valueB, stateB = next(fps.b, stateB)
return T(valueA + valueB), (stateA, stateB)
end
 
struct ProductFPS{T,A<:AbstractFPS,B<:AbstractFPS} <: AbstractFPS{T}
a::A
b::B
end
Base.:*(a::AbstractFPS{A}, b::AbstractFPS{B}) where {A,B} =
ProductFPS{promote_type(A, B),typeof(a),typeof(b)}(a, b)
 
Base.start(fps::ProductFPS{T}) where T = (start(fps.a), start(fps.b), T[], T[])
function Base.next(fps::ProductFPS{T,A,B}, st) where {T,A,B}
stateA, stateB, listA, listB = st
valueA, stateA = next(fps.a, stateA)
valueB, stateB = next(fps.b, stateB)
push!(listA, valueA)
unshift!(listB, valueB)
return T(sum(listA .* listB)), (stateA, stateB, listA, listB)
end
 
struct DifferentiatedFPS{T,A<:AbstractFPS} <: AbstractFPS{T}
a::A
end
differentiate(fps::AbstractFPS{T}) where T = DifferentiatedFPS{T,typeof(fps)}(fps)
 
function Base.start(fps::DifferentiatedFPS{T,A}) where {T,A}
s = start(fps.a)
_, s = next(fps.a, s)
n = zero(T)
return n, s
end
function Base.next(fps::DifferentiatedFPS{T,A}, st) where {T,A}
n, s = st
n += one(n)
v, s = next(fps.a, s)
return n * v, (n, s)
end
 
struct IntegratedFPS{T,A<:AbstractFPS} <: AbstractFPS{T}
a::A
k::T
end
integrate(fps::AbstractFPS{T}, k::T=zero(T)) where T = IntegratedFPS{T,typeof(fps)}(fps, k)
integrate(fps::AbstractFPS{T}, k::T=zero(T)) where T <: Integer =
IntegratedFPS{Rational{T},typeof(fps)}(fps, k)
 
Base.start(fps::IntegratedFPS{T,A}) where {T,A} = zero(T), start(fps.a)
function Base.next(fps::IntegratedFPS{T,A}, st) where {T,A}
n, s = st
iszero(n) && return fps.k, (one(n), s)
v, s = next(fps.a, s)
r::T = _div(v, n)
n += one(n)
return r, (n, s)
end
 
# Examples of FPS: constant
 
struct FiniteFPS{T} <: AbstractFPS{T}
v::NTuple{N,T} where N
end
Base.start(fps::FiniteFPS) = 1
Base.next(fps::FiniteFPS{T}, st) where T =
st > endof(fps.v) ? (zero(T), st) : (fps.v[st], st + 1)
Base.convert(::Type{FiniteFPS}, x::Real) = FiniteFPS{typeof(x)}((x,))
for op in (:+, :-, :*)
@eval Base.$op(x::Number, a::AbstractFPS) = $op(FiniteFPS(x), a)
@eval Base.$op(a::AbstractFPS, x::Number) = $op(a, FiniteFPS(x))
end
 
struct ConstantFPS{T} <: AbstractFPS{T}
k::T
end
Base.start(::ConstantFPS) = nothing
Base.next(c::ConstantFPS, ::Any) = c.k, nothing
 
struct SineFPS{T} <: AbstractFPS{T} end
SineFPS() = SineFPS{Rational{Int}}()
Base.start(::SineFPS) = 0, 1, 1
function Base.next(::SineFPS{T}, st) where T
n, fac, s = st
local r::T
if iseven(n)
r = zero(T)
else
r = _div(one(T), (s * fac))
s = -s
end
n += 1
fac *= n
return r, (n, fac, s)
end
 
struct CosineFPS{T} <: AbstractFPS{T} end
CosineFPS() = CosineFPS{Rational{Int}}()
Base.start(::CosineFPS) = 0, 1, 1
function Base.next(::CosineFPS{T}, st) where T
n, fac, s = st
local r::T
if iseven(n)
r = _div(one(T), (s * fac))
else
r = zero(T)
s = -s
end
n += 1
fac *= n
return r, (n, fac, s)
end
 
end # module FormalPowerSeries</lang>
 
'''Main''':
<lang julia>@show cosine = FormalPowerSeries.CosineFPS()
@show sine = FormalPowerSeries.SineFPS()
 
intcosine = FormalPowerSeries.integrate(cosine)
uminintsine = 1 - FormalPowerSeries.integrate(sine)
 
# Check coefficients up to the 20th term
coefsine = collect(Iterators.take(sine, 20))
coefintcosine = collect(Iterators.take(intcosine, 20))
 
coefcosine = collect(Iterators.take(cosine, 20))
coefuminintsine = collect(Iterators.take(uminintsine, 20))
 
@assert coefsine == coefintcosine "The integral of cos should be sin"
@assert coefcosine == coefuminintsine "1 minus the integral of sin should be cos"</lang>
 
{{out}}
<pre>cosine = FormalPowerSeries.CosineFPS() = 1//1 + 0//1⋅x - 1//2⋅x^2 + 0//1⋅x^3 + 1//24⋅x^4 + 0//1⋅x^5 - 1//720⋅x^6 + 0//1⋅x^7...
sine = FormalPowerSeries.SineFPS() = 0//1 + 1//1⋅x + 0//1⋅x^2 - 1//6⋅x^3 + 0//1⋅x^4 + 1//120⋅x^5 + 0//1⋅x^6 - 1//5040⋅x^7...</pre>
 
=={{header|Kotlin}}==
Anonymous user