Hi,
This is my first post to the boards about a behavior I haven’t seen yet in a forum (appreciate any direction to a post if it exists!). I was attempting to build a b-spline structure atop a polynomial structure, and to do this I have to define a family of polynomials recursively. What I’m finding is that when I call the code from REPL, eg regbn(7), I get seemingly random occurences of NaN in the polynomial coefficients. Here is my attempt at a much simplified MWE demonstrating the issue:
""" Auxilliary structure routines """
struct Poly1d{T}
deg::Int64
c::Vector{T}
function Poly1d(c::Vector)
deg = convert(Int64,length(c))-1;
S = typeof(c[1]);
return new{S}(deg,c)
end
end
function Base.:+(p₁::Poly1d,p₂::Poly1d)
deg = p₁.deg<=p₂.deg ? p₂.deg : p₁.deg;
T = typeof(p₁.c[1]+p₂.c[1]);
c = Vector{T}(undef,deg+1);
@inbounds for i=1:(deg+1)
c[i] *= 0;
c[i] += (p₁.deg+1)<=i ? p₁.c[i] : 0;
c[i] += (p₂.deg+1)<=i ? p₂.c[i] : 0;
end
return Poly1d(c)
end
""" Recursion relation """
function regbⁿ(P::Vector{Poly1d{Float64}})
n = length(P);
Q = fill(Poly1d([0.0]),n+1);
@inbounds for k=1:n+1
if k!=n+1
Q[k] += Poly1d([0.0,1.0])+P[k];
end
if k!=1
Q[k] += Poly1d([-1.0,1.0])+P[k-1];
end
end
return Q
end
function regbⁿ(deg::Integer)
P = Vector{Vector{Poly1d{Float64}}}(undef,deg+1);
P[1] = [Poly1d([1.0])];
if deg==0
return P[1]
elseif deg>0
@inbounds for k=1:deg
flagnan = true
while flagnan
P[k+1] = regbⁿ(P[k])
# Catch the erroneous NaN's
ct = 0
for i=1:length(P[k+1])
flag = isnan.(P[k+1][i].c).==true
if sum(flag)!=0
ct+=1;
end
end
if ct==0
flagnan=false
else
@warn "At P[k+1]=P[$k+1] there were $ct many polys with nan's before continued"
end
end
end
return P[end]
end
end
You’ll notice I’ve wrapped the part producing random NaN’s in a while loop that only terminates when no NaN’s are produced and warns the user how many times NaN’s occurred. I’ve also attached a screenshot of my REPL showing how the output changes despite being given the exact same input. I believe I have avoided any accidental argument mutation. The coefficients that do appear seem to be correct, and sometimes the code does run without returning any NaN’s. On the other hand, at other times calls will produce many more NaN’s than what the screenshot shows.
In the screenshot you’ll see in the first and third calls, the NaN’s appeared in different polynomials (k=4 vs k=7) and in the second call no NaN was produced.
The while loop-fix may be a workable solution, but I wish I understood what was happening better to guard against in the future.
Appreciate any insights!