2017-11-17 4 views
1

Ich schreibe eine Funktion, die die Gewichte für die baryzentrische Interpolationsformel berechnet. Ignoriert Art Stabilität, das ist einfach genug:Typstabilität für eine Funktion mit Fallunterscheidungen

function baryweights(x) 
    n = length(x) 
    if n == 1; return [1.0]; end # This is obviously not type stable 

    xmin,xmax = extrema(x) 
    x *= 4/(xmax-xmin) 
    #^Multiply by capacity of interval to avoid overflow 
    return [ 
     1/prod(x[i]-x[j] for j in 1:n if j != i) 
     for i = 1:n 
    ] 
end 

Das Problem für Typ Stabilität ist der Rückgabetyp der n > 1 Fall zu arbeiten, so kann ich ein Array des richtigen Typs im n == 1 Fall zurück. Gibt es einen einfachen Trick, um dies zu erreichen?

+0

Was ist das Ergebnis erwartet? Denn wenn ich 'baryweights ([1,2,3])' 'means parameter is' Array {Int} 'result ist' Array {Float64} '! Ist wirklich das Problem online, auf das Sie hinweisen? – Liso

+0

Ja, das ist erwünscht. Ich möchte, dass der Rückgabetyp unabhängig davon ist, was der Fall "n> 1" zurückgibt, aber dies sollte für jeden Wert von "n = 1" gelten, einschließlich "n == 1". – gTcV

+0

Aber was ist ein Anwendungsfall? Ich habe komplexe Zahlen ausprobiert, aber es funktioniert nicht mit 'Extrema'-Funktion. Können Sie einige Beispiele zeigen, bei denen sich die Typen von den Erwartungen unterscheiden? – Liso

Antwort

1

Rufen Sie einfach die Funktion rekursiv auf einem Dummy-Argument:

function baryweights(x) 
    n = length(x) 
    if n == 1 
     T = eltype(baryweights(zeros(eltype(x),2))) 
     return [one(T)] 
    end 

    xmin,xmax = extrema(x) 
    let x = 4/(xmax-xmin) * x 
     #^Multiply by capacity of interval to avoid overflow, 
     # and wrap in let to avoid another source of type instability 
     # (https://github.com/JuliaLang/julia/issues/15276) 
     return [ 
      1/prod(x[i]-x[j] for j in 1:n if j != i) 
      for i = 1:n 
     ] 
    end 
end 
+0

Hast du es getestet? Du meintest wahrscheinlich 'T = eltype (baryweights (Nullen (eltype (x), 2)))? – Liso

+0

Rechts. Nein, ich habe es wieder einmal versäumt, den Wald hinter all den Bäumen zu sehen und vergaß zu testen. Ich werde es untersuchen – gTcV

2

Ich bin nicht sicher, ob ich Ihre Pläne zu verstehen. Aber vielleicht könnte so etwas helfen? ->

baryone(t::T) where T<:Real = [1.] 
baryone(t::T) where T<:Complex = [1im] # or whatever you like here 

function baryweights(x::Array{T,1}) where T<:Number 
    n = length(x) 
    n == 1 && return baryone(x[1]) 
    xmin,xmax = extrema(x) # don't forget fix extrema for complex! :) 
    x *= 4/(xmax-xmin) 
    #^Multiply by capacity of interval to avoid overflow 
    return [ 
     1/prod(x[i]-x[j] for j in 1:n if j != i) 
     for i = 1:n 
    ] 
end 

Warnung: Ich bin immer noch Neuling! Wenn ich versuche, @code_warntype baryweights([1]) sehe ich nur viele Warnungen. (Auch wenn ich es vermeide, baryone anzurufen). Zum Beispiel n ist Any !!

Edit: ich asked on discourse und sehe jetzt, dass @code_warn Rückkehr viel besseres Ergebnis, wenn wir eine andere Variable (y) verwenden:

function baryweights(x::Array{T,1}) where T<:Number 
    n = length(x) 
    n == 1 && return baryone(x[1]) 
    xmin,xmax = extrema(x) # don't forget fix extrema for complex! :) 
    let y = x * 4/(xmax-xmin) 
     #^Multiply by capacity of interval to avoid overflow 
     return [ 
      1/prod(y[i]-y[j] for j in 1:n if j != i) 
      for i = 1:n 
     ] 
    end 
end 

Edit2: Ich let hinzugefügt y zu vermeiden sein Core.Box ed

+0

Vielen Dank für Ihr Interesse an diesem Problem! Ich war mir nicht bewusst, dass die Schließung eine andere Art von Instabilität eingeführt hat, und Sie haben auf die "Let's Workaround" hingewiesen, die mir viel Zeit beim Googlen erspart hat! – gTcV

+0

Jetzt, was ich erreichen möchte: Ich will sicher sein, dass der 'n == 1 'Fall genau den gleichen Typ wie die anderen Fälle zurückgibt, egal was der Eingabetyp ist. Ihr Workaround funktioniert, wenn eine endliche und bekannte Menge von Fällen zu berücksichtigen ist, aber selbst dann müsste ich sie alle auflisten, was mühsam, fehleranfällig und schwer zu warten ist. Der Trick mit meiner Lösung ist, dass ich garantieren kann, dass der Rückgabetyp derselbe ist, egal welchen Typ ich in meine Funktion einfüge. – gTcV

Verwandte Themen