{"id":20500574,"url":"https://github.com/juliaapproximation/recurrencerelationships.jl","last_synced_at":"2025-03-05T19:33:50.776Z","repository":{"id":252793367,"uuid":"841478196","full_name":"JuliaApproximation/RecurrenceRelationships.jl","owner":"JuliaApproximation","description":"A Julia package for solving three-term recurrence relationships","archived":false,"fork":false,"pushed_at":"2025-01-02T22:52:19.000Z","size":50,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-02-21T00:22:51.113Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Julia","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JuliaApproximation.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-12T13:41:22.000Z","updated_at":"2025-01-12T03:54:11.000Z","dependencies_parsed_at":"2024-08-18T09:22:43.865Z","dependency_job_id":"d31f922f-0606-413e-b173-82a9ff1277e2","html_url":"https://github.com/JuliaApproximation/RecurrenceRelationships.jl","commit_stats":null,"previous_names":["juliaapproximation/recurrencerelationships.jl"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaApproximation%2FRecurrenceRelationships.jl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaApproximation%2FRecurrenceRelationships.jl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaApproximation%2FRecurrenceRelationships.jl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaApproximation%2FRecurrenceRelationships.jl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JuliaApproximation","download_url":"https://codeload.github.com/JuliaApproximation/RecurrenceRelationships.jl/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242092242,"owners_count":20070485,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-15T18:21:41.097Z","updated_at":"2025-03-05T19:33:50.719Z","avatar_url":"https://github.com/JuliaApproximation.png","language":"Julia","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RecurrenceRelationships.jl\nA Julia package for solving three-term recurrence relationships\n\nThis package implements simple algorithms for computing solutions to recurrence relationships,\nincluding forward recurrence for initial value-problems, [Olver's algorithm](https://dlmf.nist.gov/3.6#v) for two-point boundary\nvalue problems, and [Clenshaw's algorithm](https://en.wikipedia.org/wiki/Clenshaw_algorithm) for computing dot products with a given vector as needed for\nevaluating expansions in orthogonal polynomials.\n\n## Forward recurrence\n\nAs an example, consider computing the first million Chebyshev U polynomials:\n\n```julia\njulia\u003e using RecurrenceRelationships\n\njulia\u003e n = 1_000_000; x = 0.1;\n\njulia\u003e @time forwardrecurrence(fill(2, n), zeros(n), ones(n), x)\n  0.006259 seconds (8 allocations: 30.518 MiB, 19.45% gc time)\n1000000-element Vector{Float64}:\n  1.0\n  0.2\n -0.96\n -0.392\n  0.8815999999999999\n  0.56832\n -0.767936\n -0.7219072000000001\n  ⋮\n  0.2777381949694639\n -0.9332843889921485\n -0.4643950727678936\n  0.8404053744385698\n  0.6324761476556076\n -0.7139101449074483\n -0.7752581766370972\n```\nNote this is faster than the explicit formula:\n```julia\njulia\u003e θ = acos(x); @time sin.((1:n) .* θ) ./ sin(θ)\n  0.010828 seconds (9 allocations: 7.630 MiB)\n1000000-element Vector{Float64}:\n  1.0\n  0.2\n -0.96\n -0.392\n  0.8816\n  0.5683199999999999\n -0.7679359999999998\n -0.7219072000000001\n  ⋮\n  0.27773819504129643\n -0.9332843889430753\n -0.46439507272938874\n  0.840405374430785\n  0.6324761477118992\n -0.713910144815891\n -0.7752581766080119\n```\nNote forward recurrence is actually more accurate than the explicit formula which can be seen by comparison with a high precision calculation (though the accuracy is worse near ±1):\n```julia\njulia\u003e norm(forwardrecurrence(fill(2, n), zeros(n), ones(n), x) - forwardrecurrence(fill(2, n), zeros(n), ones(n), big(x)))\n5.93151258729473921191879934738972139533978757730288453476821870826190721098765e-10\n\njulia\u003e norm(sin.((1:n) .* θ) ./ sin(θ) - forwardrecurrence(fill(2, n), zeros(n), ones(n), big(x)))\n4.538171757754684777956652395339636096999624380286573911589424226541646390097931e-08\n```\n\nWe can make it even faster using FillArrays.jl:\n```julia\njulia\u003e using FillArrays\n\njulia\u003e @time forwardrecurrence(Fill(2, n), Zeros(n), Ones(n), x)\n  0.003387 seconds (5 allocations: 7.630 MiB)\n1000000-element Vector{Float64}:\n  1.0\n  0.2\n -0.96\n  ⋮\n  0.6324761476556076\n -0.7139101449074483\n -0.7752581766370972\n```\n\nWe can also use LazyArrays.jl to represent Chebyshev T recurrence lazily:\n```julia\njulia\u003e using LazyArrays\n\njulia\u003e @time forwardrecurrence(Vcat(1, Fill(2, n-1)), Zeros(n), Ones(n), x)\n  0.002740 seconds (103 allocations: 7.634 MiB)\n1000000-element Vector{Float64}:\n  1.0\n  0.1\n -0.98\n -0.296\n  0.9208\n  0.48016\n -0.824768\n -0.6451136\n  0.6957452799999999\n  ⋮\n  0.9968292069233\n  0.17885499217086823\n -0.9610582084891264\n -0.3710666338686935\n  0.8868448817153877\n  0.548435610211771\n -0.7771577596730335\n -0.7038671621463777\n ```\n And this matches the explicit formula:\n ```julia\njulia\u003e @time cos.((0:n-1) .* θ)\n  0.042121 seconds (6 allocations: 7.630 MiB, 75.68% gc time)\n1000000-element Vector{Float64}:\n  1.0\n  0.1\n -0.98\n -0.29600000000000004\n  0.9208\n  0.48016000000000003\n -0.824768\n -0.6451136000000001\n  0.6957452799999999\n  ⋮\n  0.9968292069266631\n  0.178854992187329\n -0.9610582084686914\n -0.37106663377504573\n  0.8868448817354809\n  0.5484356102238197\n -0.7771577596278382\n -0.7038671620731024\n ```\n\n\n\n## Olver's algorithm\n\nOlver's algorithm is an approach to computing minimal solutions to recurrence relationships as well as solve inhomogenuous equations. A simple example is the Bessel equation following the [DLMF](https://dlmf.nist.gov/10.74#iv):\n```julia\njulia\u003e N = 1000; x = 10.0;\n\njulia\u003e a,b,c = ones(N-1), -range(2; step=2, length=N)/x, ones(N-1);\n\njulia\u003e u = olver([1; zeros(N-1)], a,b,c);\n\njulia\u003e J0 = -1/(-1 + 2sum(u[2:2:end])); # Use normalization condition\n\njulia\u003e [J0; -u*J0]\n37-element Vector{Float64}:\n -0.24593576445134843\n  0.043472746168861556\n  0.25463031368512073\n  0.058379379305186836\n -0.21960268610200867\n -0.23406152818679374\n -0.014458842084785059\n  0.21671091768505168\n  0.31785412684385733\n  0.29185568526512007\n  0.20748610663335887\n  0.12311652800159764\n  ⋮\n  1.4405452917644452e-9\n  2.762005267054569e-10\n  5.0937552445022125e-11\n  9.049766986667002e-12\n  1.5510960776464958e-12\n  2.568094792119719e-13\n  4.1122693467730146e-14\n  6.375758981501052e-15\n  9.573158101767982e-16\n  1.339885277011767e-16\n -1.9396116268561495e-17\n```\nThis matches the special functions definition:\n```julia\njulia\u003e [besselj(k,x) for k=0:36]\n37-element Vector{Float64}:\n -0.2459357644513483\n  0.04347274616886144\n  0.25463031368512057\n  0.058379379305186795\n -0.2196026861020085\n -0.23406152818679363\n -0.014458842084785123\n  0.2167109176850515\n  0.31785412684385717\n  0.29185568526512007\n  0.20748610663335898\n  0.1231165280015976\n  ⋮\n  1.4405452917644441e-9\n  2.7620052670546077e-10\n  5.093755244504228e-11\n  9.049766986775815e-12\n  1.5510960782574664e-12\n  2.568094827689877e-13\n  4.112271491025767e-14\n  6.3758926566612455e-15\n  9.581766237065793e-16\n  1.3970838454349004e-16\n  1.9782068097851055e-17\n```\n\n## Clenshaw's algorithm\n\nClenshaw's algorithm is an efficient way to compute expansions in orthogonal polynomials. Here we compute\n$$\n∑_{k=0}^{n-1} {U_k(x) \\over k+1}\n$$\nfor $x = 0.1$ and $n = 1,000,000$:\n\n```julia\njulia\u003e @time clenshaw(inv.(1:n), fill(2, n), zeros(n), ones(n+1), x)\n  0.006446 seconds (12 allocations: 30.518 MiB)\n0.8396901361362448\n```\n\nThis matches the explicit expression:\n```julia\njulia\u003e @time sum(sin((k+1)*θ)/(k+1) for k=0:n-1)/sin(θ)\n  0.161225 seconds (8.03 M allocations: 124.408 MiB, 2.74% gc time, 16.44% compilation time)\n0.8396901361362544\n```\n\nAgain, using FillArrays.jl is faster. And we can use InfiniteArrays.jl to allow any length of\ncoefficients:\n```julia\njulia\u003e using InfiniteArrays\n\njulia\u003e @time clenshaw(inv.(1:n), Fill(2, ∞), Zeros(∞), Ones(∞), x)\n  0.004574 seconds (5 allocations: 7.630 MiB)\n0.8396901361362448\n```\n\nClenshaw also supports in-place usage including a matrix of coefficients. This can be used to evaluate 2D polynomials, eg.\n$$\nf(x,y) = ∑_{k=1}^{n} ∑_{j=1}^n T_k(x) U_j(y) (k+2j)\n$$\ncan be evaluated via:\n```julia\njulia\u003e m,n = 5,6;\n\njulia\u003e coeffs = ((1:m) .+ 2(1:n)');\n\njulia\u003e x,y = 0.1,0.2;\n\njulia\u003e A, B, C = Fill(2,n), Zeros{Int}(n), Ones{Int}(n+1);\n\njulia\u003e clenshaw(vec(clenshaw(coeffs, x; dims=1)), A, B, C, y)\n9.358401024\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuliaapproximation%2Frecurrencerelationships.jl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjuliaapproximation%2Frecurrencerelationships.jl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuliaapproximation%2Frecurrencerelationships.jl/lists"}