-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
resizeDefault
allowing a 'fill' element if the dimensions are short
#59
Comments
If there is a will, there is a way :D You bring up an interesting question. A solution with exact type signature you presented is not possible without some major change to underlying structure of the library, but that would be a wrong way to go about it anyways. I am not sure if I will add any of the solutions to the library, but free to use either one of them Here is a naive and less optimal solution to the problem: defaultResizeNaive :: (Construct r ix' e, Source r ix e) => e -> ix' -> Array r ix e -> Array D ix' e
defaultResizeNaive e newsz arr =
makeArray (getComp arr) newsz $
handleBorderIndex (Fill e) oldsz (unsafeIndex arr) . fromLinearIndex oldsz . toLinearIndex newsz
where oldsz = size arr It is sub-optimal because it has to check if index doesn't go out of bounds for every element of new array. But the good thing is that resulting array is A more involved solution is to actually iterate over the old array while loading it's elements into the new array, and if there is any unfilled space leftover fill it with default value: defaultResize :: (Source r ix e, Mutable r' ix' e) => e -> ix' -> Array r ix e -> Array r' ix' e
defaultResize e newsz' arr =
unsafePerformIO $ do
let newsz = liftIndex (max 0) newsz'
oldsz = size arr
knew = totalElem newsz
kold = min (totalElem oldsz) knew
comp = getComp arr
marr <- unsafeNew newsz
case comp of
Seq -> do
loopM_ 0 (< kold) (+ 1) $ \i -> unsafeLinearWrite marr i (unsafeLinearIndex arr i)
loopM_ kold (< knew) (+ 1) $ \i -> unsafeLinearWrite marr i e
ParOn wIds ->
withScheduler_ wIds $ \scheduler -> do
splitLinearlyWith_
(numWorkers scheduler)
(scheduleWork scheduler)
kold
(unsafeLinearIndex arr)
(unsafeLinearWrite marr)
let slack = knew - kold
splitLinearlyWith_
(numWorkers scheduler)
(scheduleWork scheduler)
slack
(const e)
(unsafeLinearWrite marr . (+ kold))
unsafeFreeze comp marr The interesting part about the problem and this last solution is that it would be possible to create a delayed array as well, but of a different kind, namely a "push" array. I've been pondering on this idea for couple of weeks now and considering implementing this new kind of delayed array, we'll see. This would allow nicer solutions for a new class of problems, including this one. cc @ocramz Thanks for pointing out the topic of Pull/Push arrays to me at Haskell Exchange, it already comes in handy ;) |
Wow, I didn't realize it was this tricky! Ultimately, I'd be after a Also, do you have any links about push/pull arrays I could read? |
Here is a paper that gives a nice introduction to push pull arrays, but then goes into more stuff: https://svenssonjoel.github.io/writing/defuncEmb.pdf |
Now that push arrays are available in massiv we can easily implement this function. |
Is there a way to do something like
This will use the supplied
e
to 'fill in' any elements needed to resize that don't exist in the argument array. For example:should produce
The text was updated successfully, but these errors were encountered: