2017-11-17 13 views
1

重心補間式の重みを計算する関数を書いています。タイプの安定性を無視し、それが十分に簡単です:大文字小文字区別を含む関数の型安定度

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 

タイプの安定性のための問題は、私はn == 1た場合の正しい型の配列を返すことができるようにn > 1例戻り値の型をうまくすることです。これを達成するための簡単なトリックはありますか?

+0

何期待される結果ですか? 'baryweights([1,2,3]) 'と呼ぶと、パラメータが' Array {Int} 'であることを意味します。結果は' Array {Float64} 'です!あなたが指摘しているライン上の問題は本当ですか? – Liso

+0

はい、それが望ましいです。戻り値の型を 'n> 1'の場合の戻り値と同じにしたいが、' n == 1 'を含む 'n = 1'の値についてはそうでなければならない。 – gTcV

+0

しかし、ユースケースは何ですか?私は複素数を試しましたが、 'extrema'関数では動作しません。タイプが期待と異なる場合のいくつかの例を示してください。 – Liso

答えて

1

は単に仮引数に再帰関数を呼び出す:

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

テストしましたか?あなたはたぶん 'T = eltype(重さ(ゼロ、eltype(x)、2)))')を意味していました。 – Liso

+0

右。いいえ、私はもう一度、すべての木の背後にある森を見逃して、テストするのを忘れました。私はそれを見てください – gTcV

2

私は私はあなたの計画を理解している場合わかりません。しかし、おそらくこのような何かが助けることができますか? - >

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 

警告:私はまだ初心者です!私が試してみたら@code_warntype baryweights([1])私はちょうどたくさんの警告を見る。 (もし私がbaryoneに電話するのを避けても)。たとえば、nAnyです。

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:

編集:私たちは別の変数(y)を使用している場合、今 I asked on discourseとは、その@code_warnリターンより良い結果を参照してくださいCore.Box EDになるようにyを避けるために、私はletを追加しまし

+0

この問題に興味を持っていただきありがとうございます!私は閉鎖によって別のタイプの不安定性が導入されたことに気づいていませんでした。あなたは 'let'の回避策を指摘して私にグーグル・グーグルの時間を節約しました! – gTcV

+0

私は達成したいことについて: 'n == 1'の場合は、入力の種類に関係なく、他の場合とまったく同じ型を返すようにしたいと思います。考慮すべき有限かつ既知のケースがあれば、あなたの回避策が機能しますが、それでも退屈でエラーが発生しやすく、保守が難しいすべてをリストする必要があります。私の解決策のトリックは、あなたが私の関数にどのような型を与えても、戻り値の型が同じであることを保証できるということです。 – gTcV

関連する問題