2013-04-09 25 views
1

我正在使用Repa編寫地形生成器。發生器首先創建一個DIM2接地片,並且我希望能夠在其上添加DIM2片以創建DIM3陣列。將較低維度的切片與較高維度相結合修復陣列

想象一個3x3x3盒子。如果我有3x3的切片,我可以將切片放在盒子的頂部以垂直增長。這正是我想要用Repa做的事情。我有一個似乎用traverse2工作的實現:

stack :: (Shape sh, Source r c, Source r2 c)              
     => Array r (sh :. Int) c -> Array r2 sh c -> Array D (sh :. Int) c             
stack arr1 arr2 = traverse2 arr1 arr2 resize $ \f g [email protected](sh' :. _) ->               
    if extent arr1 `inShape` sh then f sh else g sh'                  
    where resize :: Shape (sh :. Int) => (sh :. Int) -> t -> (sh :. Int)             
      resize (xs :. x) _ = xs :. (x + 1) 

這將構建具有較高維數組的同一維度的新數組,結果數組的大小在更高的層面增加了一個。

即。 stack (3x3x3 box :: DIM3) (3x3 slice :: DIM2) == (3x3x4 box :: DIM3)

該方法需要對兩個數組進行全面遍歷,並且非常混亂且可能出錯。有更清潔,更有效的方法來將低維Repa陣列與更高維數組合在一起嗎?

回答

1

如果可以切換尺寸並使切片索引位於最上方,則可以使用Partitioned陣列重新編碼。不短,但更加清晰:

import Data.Array.Repa 
import Data.Array.Repa.Repr.Partitioned 

stack :: (Source r c, Source r2 c) 
     => Array r DIM3 c -> Array r2 DIM2 c -> Array (P r D) DIM3 c 
stack box slice = APart newBoxExt range box extendedSlice 
    where 
    -- maybe there is a standard function for this, I didn't find 
    extendedSlice = 
     fromFunction 
      (Z :. 1 :. w :. h) 
      (\(Z :. _ :. w :. h) -> slice `index` (Z :. w :. h)) 
    range = Range zeroDim boxExt (inShapeRange zeroDim boxExt) 
    newBoxExt = (Z:. boxSlices + 1 :. w :. h) 
    [email protected](Z :. boxSlices :. w :. h) = extent box 

這是很難在comparsion來估計該決定的效率,以沒有你的有關生成的陣列使用模式knowlege。

通常,爲了使repa庫和其他類似的庫具有更好的性能,這些數據結構需要以「更多功能」方式填充,理想情況下是單通道。在你的情況下,我會考慮處理(在磁盤上繪圖,寫在磁盤上,你將要做的)切片,或者如果它們最終連接在一起,發明類似整個切片上的摺疊操作。