diff options
| author | Tom Smeding <tom@tomsmeding.com> | 2025-11-26 22:44:44 +0100 |
|---|---|---|
| committer | Tom Smeding <tom@tomsmeding.com> | 2025-11-26 22:44:44 +0100 |
| commit | 829109ba73211394691d5789f35a23120feaf3f6 (patch) | |
| tree | df523326d0a7f6c6698e2b1aae7d177c17de792a /src/Data/Array/Nested/Mixed | |
| parent | 2177f3e9cdb8a1f10529f678d5dad9d8c7d60d86 (diff) | |
Benchmark and improve ixxFromLinear
Diffstat (limited to 'src/Data/Array/Nested/Mixed')
| -rw-r--r-- | src/Data/Array/Nested/Mixed/Shape.hs | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/src/Data/Array/Nested/Mixed/Shape.hs b/src/Data/Array/Nested/Mixed/Shape.hs index 1b008e5..f127e3a 100644 --- a/src/Data/Array/Nested/Mixed/Shape.hs +++ b/src/Data/Array/Nested/Mixed/Shape.hs @@ -262,18 +262,30 @@ ixxZipWith _ ZIX ZIX = ZIX ixxZipWith f (i :.% is) (j :.% js) = f i j :.% ixxZipWith f is js ixxFromLinear :: IShX sh -> Int -> IIxX sh -ixxFromLinear = \sh i -> case go sh i of - (idx, 0) -> idx - _ -> error $ "ixxFromLinear: out of range (" ++ show i ++ - " in array of shape " ++ show sh ++ ")" +ixxFromLinear = \sh -> -- give this function arity 1 so that suffixes is shared when it's called many times + let suffixes = drop 1 (scanr (*) 1 (shxToList sh)) + in \i -> + if i < 0 then outrange sh i else + case (sh, suffixes) of -- unfold first iteration of fromLin to do the range check + (ZSX, _) | i > 0 -> outrange sh i + | otherwise -> ZIX + (n :$% sh', suff : suffs) -> + let (q, r) = i `quotRem` suff + in if q >= fromSMayNat' n then outrange sh i else + q :.% fromLin sh' suffs r + _ -> error "impossible" where - -- returns (index in subarray, remaining index in enclosing array) - go :: IShX sh -> Int -> (IIxX sh, Int) - go ZSX i = (ZIX, i) - go (n :$% sh) i = - let (idx, i') = go sh i - (upi, locali) = i' `quotRem` fromSMayNat' n - in (locali :.% idx, upi) + fromLin :: IShX sh -> [Int] -> Int -> IxX sh Int + fromLin ZSX _ !_ = ZIX + fromLin (_ :$% sh') (suff : suffs) i = + let (q, r) = i `quotRem` suff -- suff == shrSize sh' + in q :.% fromLin sh' suffs r + fromLin _ _ _ = error "impossible" + + {-# NOINLINE outrange #-} + outrange :: IShX sh -> Int -> a + outrange sh i = error $ "ixxFromLinear: out of range (" ++ show i ++ + " in array of shape " ++ show sh ++ ")" ixxToLinear :: IShX sh -> IIxX sh -> Int ixxToLinear = \sh i -> fst (go sh i) |
