2017-12-07 7 views
2

Data.Vectorには、そのベクトルのmaximum値を返すタイプmaxIndex :: (Ord a) => Vector a -> Intの関数maxIndexが含まれています。私は可変ベクトルで作業していますが、MVectorにはmaxIndexが定義されていません。MVectorのmaxIndex

私は持っているデータを取得する最良の方法は何ですかMVector私は持っていますか?私のコードは、現在、次のとおりです。

i
import qualified Data.Vector.Unboxed.Mutable as MV 
import   Control.Monad.ST 
import   Control.Monad    (mapM_) 

type MaxIndex = Int 

step :: forall s. MV.MVector s Int -> MaxIndex -> ST s() 
step vec i = do 
    n <- MV.unsafeRead vec i 
    MV.write vec i 0 
    let l  = MV.length vec 
     (k, x) = n `divMod` l 
    mapM_ (\j -> MV.modify vec (+k) j) [0..l-1] -- side note, this is just 
               -- fmap (+k) vec, but MVector is not 
               -- a functor. Is there a better way? 
    mapM_ (\j -> MV.modify vec (+1) (j `mod` l)) [i+1..i+x] 

は私がstepの内側に誘導するために探していたインデックスです。私はこれをやっています。なぜなら、ここでの行動は最終的にuntilの中にラップされ、述語が満たされるまで繰り返され、毎回の凍結と解凍は馬鹿げたほど高価に聞こえるからです。

+0

はい私はそれを参照してください。もし私が書くことができる前に '(安全ではない)Thaw'をもう一度しなければならないのですか? –

+1

安全でない凍結は原則として非常に安く、実際には何もしません。そして、いいえ、モナド計算を再開する前にmax-indexを厳密に評価すれば、何か解凍する必要はないと思います。しかし、より良いテスト&ベンチそれ... – leftaroundabout

+0

@leftaroundabhrm私は、混乱しています。 MVectorが不変の 'Vector'にフリーズするのを確実にしないと' unsafeFreeze'は何をしますか?すでに完了している場合は、どのようにしてメモリ上のその位置に書き込むことができますか? –

答えて

1

このメモリを後で変更しようとしているので、安全でない凍結について多くの話題があります。したがって、unsafeFreezeを呼び出すときに暗黙のうちに保証していることに違反します。

私の提案は、命令型のmaxIndex関数を書くことです。以下は入力されていますが、テストされていません:

import qualified Data.Vector.Unboxed.Mutable as MV 
import   Control.Monad.ST 
import   Control.Monad    (mapM_) 

maxIndex :: (Ord a, MV.Unbox a) => MV.MVector s a -> ST s (Maybe Int) 
maxIndex mv | len == 0 = pure Nothing 
      | otherwise = Just <$> go 0 0 
where 
len = MV.length mv 
go n i | i >=len = pure n 
     | otherwise = do 
    nVal <- MV.unsafeRead mv n 
    iVal <- MV.unsafeRead mv i 
    if nVal < iVal then go i (i+1) 
        else go n (i+1) 
+0

質問:森の中の樹木を突然変異させて、スタジアムが必要なエルフがすでに消えてしまっても、それでも騒音は出ますか? – leftaroundabout

+0

これは私のためにはうまくいっていて、 'unsafe'という名前の関数によって作られた正確な約束を酷使しているように見えませんでした。ご協力いただきありがとうございます!それが価値があることについては、私の述語が 'Data.Set.member'なので、これらの結果を' Data.Set.Set'に保存するために、これらの結果をフリーズする必要があることが遅すぎることがわかりました。私は、変更を無視し、この実装のための不変のベクトルの束を生成することを選択しましたが、集められた洞察はまだ非常に有用です! –

1

unsafeFreezeと速いと思われるベクトルをフリーズすることを検討しましたか(つまりΘ(1))?たとえば、次のように変更可能なベクターについてmaxIndexを定義することができます

maxIndex = fmap V.maxIndex . V.unsafeFreeze 

これは、あなたが次のことをインポートしていることを前提としています

import qualified Data.Vector.Unboxed   as V 

unsafeFreezeは、実際にデータをコピーしないと高速である必要がありますが、それこのアプローチが明示的なループに比べて実際に速いかどうかを見るために基準ベンチマークを実行することは面白いでしょう。

+0

私は彼が突然変異を実行する前にmaxIndexを必要とするので、彼の状況ではうまくいくはずですが、 'get max index;突然変異1;強制最大指数;最初の突然変異の後に配列が立っているので、浮動小数点やその他の最適化でインデックスを得ることができると強く思っています。この複雑さが私がunsafeFreezeオプションを阻止する理由です。 –

関連する問題