Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f6a1703
create type for irrationals, reconfigure iterators
simonbyrne Jul 1, 2015
d8b0e6d
minor fixes
simonbyrne Jul 12, 2015
f031b0b
add name to LICENSE
simonbyrne Jul 12, 2015
328cd9b
Merge branch 'pr/10' into pr10-update
inkydragon Dec 31, 2024
ded89d9
bug: update old julia type def style
inkydragon Dec 31, 2024
5372d25
bug: fix all function type sign
inkydragon Dec 31, 2024
5acefe6
test: carry OEIS.jl
inkydragon Dec 31, 2024
9e988ee
bug.irrational: fix precision/setprecision
inkydragon Dec 31, 2024
d4dd8f7
test: add tests for eltype(::ContinuedFraction)
inkydragon Dec 31, 2024
8628690
sty: format exports
inkydragon Dec 31, 2024
f0389ae
doc: add doc for abstract type ContinuedFraction
inkydragon Dec 31, 2024
17004f9
api: simplify continuedfraction(x::Rational{T})
inkydragon Dec 31, 2024
b6438ba
api: export and test `quotients`
inkydragon Dec 31, 2024
69e5ae6
doc: add doc for struct FiniteContinuedFraction
inkydragon Dec 31, 2024
c648f37
doc: add docstr for continuedfraction
inkydragon Dec 31, 2024
89a68ea
test: add tests for continuedfraction
inkydragon Dec 31, 2024
253e1a8
api: fix Iteration Interfaces for all types
inkydragon Dec 31, 2024
2c0ce7d
test: fix missing import
inkydragon Dec 31, 2024
268d38a
test: add to testset "OEIS"
inkydragon Dec 31, 2024
90a8beb
tests: rename `test\oeis_ref.jl`
inkydragon Dec 31, 2024
2a730c8
doc: add doc for `convergents(x::Real)`
inkydragon Dec 31, 2024
a74357f
doc: add doc for `ConvergentIterator`
inkydragon Dec 31, 2024
5ba9627
doc: add doc for `IrrationalContinuedFraction`
inkydragon Dec 31, 2024
1de4437
sty: group code
inkydragon Dec 31, 2024
59310ca
api: add kw `prec::Int=precision(BigFloat)` for continuedfraction
inkydragon Dec 31, 2024
98d9b2e
doc: add for continuedfraction
inkydragon Dec 31, 2024
da6b920
test: add tests for continuedfraction(IrrationalContinuedFraction)
inkydragon Dec 31, 2024
88f01de
bug: fix IteratorSize(::Type{IrrationalContinuedFraction})
inkydragon Dec 31, 2024
dc5e85a
tests.IrrationalCF: test Iteration Interfaces
inkydragon Dec 31, 2024
f501d98
tests.IrrationalCF: test Special cases for getindex
inkydragon Dec 31, 2024
6d369a5
enh: allow get-range `cf[1:5]` for ContinuedFraction
inkydragon Dec 31, 2024
a718b0c
tests.FiniteCF: test Iteration Interfaces
inkydragon Dec 31, 2024
64351f1
enh: generalize convergents(x...)
inkydragon Dec 31, 2024
13eeb42
tests: add for ConvergentIterator
inkydragon Dec 31, 2024
0f525e7
bug: typo fix `MathConstants.ℯ`
inkydragon Dec 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
*.jl.*.cov
*.jl.cov
*.jl.mem
/Manifest.toml
/docs/Manifest.toml
Manifest.toml
/docs/build/
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ContinuedFractions.jl is licensed under the MIT License:

> Copyright (c) 2013: John Myles White and other contributors.
> Copyright (c) 2013: John Myles White, Simon Byrne and other contributors.
>
> Permission is hereby granted, free of charge, to any person obtaining
> a copy of this software and associated documentation files (the
Expand Down
152 changes: 20 additions & 132 deletions src/ContinuedFractions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,24 @@ This module provides functionality for working with continued fractions.
"""
module ContinuedFractions

import Base: iterate, IteratorSize, IteratorEltype, HasLength, HasEltype,
length, eltype, collect
import Base: IteratorSize, iterate, length, eltype, isdone, getindex

export ContinuedFraction, quotients, convergents, ConvergentIterator
export ContinuedFraction, continuedfraction, quotients,
FiniteContinuedFraction,
IrrationalContinuedFraction,
ConvergentIterator, convergents

"""
struct ContinuedFraction{T} where {T<:Integer} end

ContinuedFraction(qs::Vector{T}) where {T<:Integer}
ContinuedFraction(rat::Rational{T}) where {T<:Integer}
ContinuedFraction(x::AbstractFloat)
ContinuedFraction(x::Integer)

A type representing a continued fraction with integer quotients.

# Fields
The fields of a structure are *not* part of the public API.
Please use helper functions to access them, such as [`quotients`](@ref).

# Examples
```jldoctest
julia> ContinuedFraction([1])
ContinuedFraction{Int64}([1])

julia> ContinuedFraction(1)
ContinuedFraction{Int64}([1])

julia> ContinuedFraction(10)
ContinuedFraction{Int64}([10])

julia> ContinuedFraction(3.14)
ContinuedFraction{Int64}([3, 7, 7])

julia> ContinuedFraction(big"1"/10)
ContinuedFraction{BigInt}(BigInt[0, 10])
```
"""
struct ContinuedFraction{T}
quotients::Vector{T}
ContinuedFraction{T}(qs::Vector{T}) where {T<:Integer} = new{T}(qs)
end
ContinuedFraction{T<:Integer}

eltype(it::ContinuedFraction{T}) where {T} = T
An abstract type representing a continued fraction with elements of type `T`,
where `T` is a subtype of `Integer`.
This type serves as a base for defining specific types of continued fractions.
"""
abstract type ContinuedFraction{T<:Integer} end

eltype(::ContinuedFraction{T}) where {T<:Integer} = T

"""
quotients(cf::ContinuedFraction) -> Vector{T}
Expand All @@ -55,104 +29,18 @@ Return the quotients of the given `ContinuedFraction` object `cf`.

# Returns
- A vector containing the quotients of the continued fraction.

# Examples
```jldoctest
julia> quotients(ContinuedFraction(10))
1-element Vector{Int64}:
10

julia> quotients(ContinuedFraction(3.14))
3-element Vector{Int64}:
3
7
7

julia> quotients(ContinuedFraction(big"1"/10))
2-element Vector{BigInt}:
0
10
```
"""
quotients(cf::ContinuedFraction) = cf.quotients

struct ConvergentIterator{T}
qs::Vector{T}
ConvergentIterator{T}(qs::Vector{T}) where {T<:Integer} = new{T}(qs)
end
ConvergentIterator(qs::Vector{T}) where {T<:Integer} = ConvergentIterator{T}(qs)

_done(it::ConvergentIterator, state::Int) = state > length(it.qs)
function Base.iterate(it::ConvergentIterator, state::Int = 1)
_done(it, state) && return nothing
convergent = Rational(ContinuedFraction(it.qs[1:state]))
convergent, state + 1
end

IteratorSize(::Type{ConvergentIterator}) = HasLength()
IteratorEltype(::Type{ConvergentIterator}) = HasEltype()

length(it::ConvergentIterator) = length(it.qs)
eltype(::Type{ConvergentIterator{T}}) where {T} = Rational{T}
eltype(it::ConvergentIterator{T}) where {T} = Rational{T}
collect(it::ConvergentIterator{T}) where {T} = collect(Rational{T}, it)

"""
convergents(cf::ContinuedFraction) -> ConvergentIterator
convergents(qs::Vector{<:Integer}) -> ConvergentIterator
convergents(x::Real) -> ConvergentIterator

Compute the convergents of a input.

# Returns
- `ConvergentIterator`: An iterator over the convergents of the continued fraction.

# Examples
```jldoctest
julia> convergents([0])
ConvergentIterator{Int64}([0])

julia> convergents(3)
ConvergentIterator{Int64}([3])

julia> convergents(22/7)
ConvergentIterator{Int64}([3, 7])

julia> convergents(355/113)
ConvergentIterator{Int64}([3, 7, 16])

julia> convergents(3.1415926)
ConvergentIterator{Int64}([3, 7, 15, 1, 243, 1, 1, 9, 1, 1, 4])
```
"""
convergents(cf::ContinuedFraction) = convergents(quotients(cf))
convergents(qs::Vector{<:Integer}) = ConvergentIterator(qs)
convergents(x::Real) = convergents(ContinuedFraction(x))

function Base.Rational(cf::ContinuedFraction)
qs = quotients(cf)
isempty(qs) && return 0 // 1
length(qs) == 1 && return qs[1] // 1

remainder = qs[2:end]
rat = Rational(ContinuedFraction(remainder))
(qs[1] * rat.num + rat.den) // rat.num
end

function ContinuedFraction(rat::Rational{T}) where {T<:Integer}
a = div(rat.num, rat.den)
a * rat.den == rat.num && return ContinuedFraction(T[a]) # Exact!
quotients(cf::ContinuedFraction)

cf = ContinuedFraction(rat.den//(rat.num - a*rat.den))
pushfirst!(quotients(cf), a) # insert at index 1
cf
#= Iteration Interfaces =#
# Syntax like cf[1:end]
function getindex(cf::ContinuedFraction{T}, r::AbstractRange) where {T<:Integer}
return T[ cf[i] for i in r ]
end

# let rationalize handle conversion from floating point
ContinuedFraction(x::BigFloat) = ContinuedFraction(rationalize(BigInt, x))
ContinuedFraction(x::AbstractFloat) = ContinuedFraction(rationalize(x))

ContinuedFraction(x::Integer) = ContinuedFraction([x])
ContinuedFraction(qs::Vector{T}) where {T<:Integer} = ContinuedFraction{T}(qs)
include("finite.jl")
include("irrational.jl")
include("convergents.jl")

end # module ContinuedFractions
49 changes: 49 additions & 0 deletions src/convergents.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

"""
ConvergentIterator{T<:Integer, CF<:ContinuedFraction{T}}
ConvergentIterator(cf::ContinuedFraction{T}) where {T<:Integer}

An iterator type for generating the convergents of a continued fraction.

# Fields
The fields of a structure are *not* part of the public API.
"""
struct ConvergentIterator{T<:Integer, CF<:ContinuedFraction{T}}
cf::CF
end

#= Iteration Interfaces =#
Base.IteratorSize(::ConvergentIterator{T,CF}) where {T,CF} = Base.IteratorSize(CF)
Base.length(it::ConvergentIterator) = length(it.cf)
Base.eltype(it::ConvergentIterator{T,CF}) where {T,CF} = Rational{T}
"""
(Int, Rational{T}, Rational{T})
"""
const ConvStateType{T} = Tuple{Int, Rational{T}, Rational{T}} where {T<:Integer}
Base.isdone(it::ConvergentIterator{T,CF}, state::ConvStateType{T}) where {T<:Integer,CF} =
isdone(it.cf, state[1])
function Base.iterate(it::ConvergentIterator{T,CF}, state::ConvStateType{T}) where {T<:Integer,CF}
i, r, r_prev = state
q, i_next = iterate(it.cf, i)
r_next = (q*r.num + r_prev.num) // (q*r.den + r_prev.den)
return r_next, (i_next, r_next, r)
end
Base.iterate(it::ConvergentIterator{T,CF}) where {T<:Integer,CF} =
iterate(it, (1, one(T)//zero(T), zero(T)//one(T)))


"""
convergents(x...) -> ConvergentIterator

Compute the convergents of a input.

# Returns
- `ConvergentIterator`: An iterator over the convergents of the continued fraction.

See [`continuedfraction`](@ref)

# Examples
```
```
"""
convergents(x...) = ConvergentIterator(continuedfraction(x...))
96 changes: 96 additions & 0 deletions src/finite.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@

"""
FiniteContinuedFraction{T<:Integer}

A type of representation of **rational numbers** using
*finite* term connected fractions with Integer quotients.

# Fields
The fields of a structure are *not* part of the public API.
Please use helper functions to access them, such as [`quotients`](@ref).

# Examples
"""
struct FiniteContinuedFraction{T<:Integer} <: ContinuedFraction{T}
quotients::Vector{T}
end

#= Helper functions for access internal fields =#
"""
quotients(cf::FiniteContinuedFraction)
"""
quotients(cf::FiniteContinuedFraction) = cf.quotients

#= Helper functions for construct FiniteContinuedFraction =#
"""
continuedfraction(x::Real, y::Real, ::Type{T}=Int)

Build continued fraction from the ratio of `x` and `y`.

# Examples
```jldoctest
julia> continuedfraction(3, 9)
FiniteContinuedFraction{Int64}([0, 3])

julia> continuedfraction(9, 3)
FiniteContinuedFraction{Int64}([3])

julia> continuedfraction(11, 9)
FiniteContinuedFraction{Int64}([1, 4, 2])
```
"""
function continuedfraction(x::Real, y::Real, ::Type{T}=Int) where {T<:Integer}
qs = T[]
r = y
r_p = x

while r != 0
q, r_n = divrem(r_p, r)
push!(qs, q)
r, r_p = r_n, r
end
FiniteContinuedFraction(qs)
end

"""
continuedfraction(x::AbstractFloat, ::Type{T}=Int)

Build continued fraction from float point number `x`.

# Examples
```jldoctest
julia> continuedfraction(0.0)
FiniteContinuedFraction{Int64}([0])

julia> continuedfraction(1.0)
FiniteContinuedFraction{Int64}([1])

julia> continuedfraction(0.5)
FiniteContinuedFraction{Int64}([0, 2])
```
"""
continuedfraction(x::AbstractFloat, ::Type{T}=Int) where {T<:Integer} =
continuedfraction(x, one(x), T)

"""
continuedfraction(x::Rational{T})

Build continued fraction from Rational number `x`.

# Examples
```jldoctest
julia> continuedfraction(0//1)
FiniteContinuedFraction{Int64}([0])
```
"""
continuedfraction(x::Rational{T}) where {T<:Integer} =
continuedfraction(x.num, x.den, T)

#= Iteration Interfaces =#
Base.length(cf::FiniteContinuedFraction) = length(quotients(cf))
Base.isdone(cf::FiniteContinuedFraction, idx::Int=1) = idx > length(cf)
Base.getindex(cf::FiniteContinuedFraction, i::Int) = getindex(quotients(cf), i)
function Base.iterate(cf::FiniteContinuedFraction, idx::Int=1)
isdone(cf, idx) && return nothing
cf[idx], state + 1

Check warning on line 95 in src/finite.jl

View check run for this annotation

Codecov / codecov/patch

src/finite.jl#L93-L95

Added lines #L93 - L95 were not covered by tests
end
Loading
Loading