diff --git a/.github/workflows/haskell-ci.yml b/.github/workflows/haskell-ci.yml index 3a6f105..c70a98f 100644 --- a/.github/workflows/haskell-ci.yml +++ b/.github/workflows/haskell-ci.yml @@ -39,7 +39,7 @@ jobs: curl -sL https://downloads.haskell.org/ghcup/0.1.19.2/x86_64-linux-ghcup-0.1.19.2 > "$HOME/.ghcup/bin/ghcup" chmod a+x "$HOME/.ghcup/bin/ghcup" "$HOME/.ghcup/bin/ghcup" install ghc "$HCVER" || (cat "$HOME"/.ghcup/logs/*.* && false) - "$HOME/.ghcup/bin/ghcup" install cabal 3.10.1.0 || (cat "$HOME"/.ghcup/logs/*.* && false) + "$HOME/.ghcup/bin/ghcup" install cabal 3.10.2.0 || (cat "$HOME"/.ghcup/logs/*.* && false) env: HCKIND: ${{ matrix.compilerKind }} HCNAME: ${{ matrix.compiler }} @@ -55,7 +55,7 @@ jobs: echo "HC=$HC" >> "$GITHUB_ENV" echo "HCPKG=$HOME/.ghcup/bin/$HCKIND-pkg-$HCVER" >> "$GITHUB_ENV" echo "HADDOCK=$HOME/.ghcup/bin/haddock-$HCVER" >> "$GITHUB_ENV" - echo "CABAL=$HOME/.ghcup/bin/cabal-3.10.1.0 -vnormal+nowrap" >> "$GITHUB_ENV" + echo "CABAL=$HOME/.ghcup/bin/cabal-3.10.2.0 -vnormal+nowrap" >> "$GITHUB_ENV" HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\d+)\.(\d+)\.(\d+)(\.(\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))') echo "HCNUMVER=$HCNUMVER" >> "$GITHUB_ENV" echo "ARG_TESTS=--enable-tests" >> "$GITHUB_ENV" diff --git a/cabal.project.benchmarking b/cabal.project.benchmarking index 7a225aa..00ba227 100644 --- a/cabal.project.benchmarking +++ b/cabal.project.benchmarking @@ -1,5 +1,4 @@ -packages: **/*.cabal -benchmarks: true +import: cabal.project -- Optimization level for the package itself optimization: 2 diff --git a/cabal.project.profiling b/cabal.project.profiling index 34cb2d3..9193038 100644 --- a/cabal.project.profiling +++ b/cabal.project.profiling @@ -1,13 +1,6 @@ -packages: **/*.cabal -test-show-details: streaming +import: cabal.project.benchmarking -- Optimization level for the package itself profiling: True library-profiling: True -executable-profiling: True -optimization: 2 - --- Required to optimize all dependencies as well -package * - optimization: 2 - documentation: false \ No newline at end of file +executable-profiling: True \ No newline at end of file diff --git a/javelin/src/Data/Series.hs b/javelin/src/Data/Series.hs index 3f941d8..e9d945c 100644 --- a/javelin/src/Data/Series.hs +++ b/javelin/src/Data/Series.hs @@ -697,7 +697,7 @@ require :: Ord k => Series k a -> Index k -> Series k (Maybe a) require = G.require --- | Drop the index of a series by replacing it with an `Int`-based index. Values will +-- | \(O(n)\) Drop the index of a series by replacing it with an `Int`-based index. Values will -- be indexed from 0. -- -- >>> let xs = Series.fromList [("Paris", 1 :: Int), ("London", 2), ("Lisbon", 4)] diff --git a/javelin/src/Data/Series/Generic/View.hs b/javelin/src/Data/Series/Generic/View.hs index fc12553..c59333c 100644 --- a/javelin/src/Data/Series/Generic/View.hs +++ b/javelin/src/Data/Series/Generic/View.hs @@ -27,6 +27,7 @@ module Data.Series.Generic.View ( ) where +import Data.Functor ( (<&>) ) import Data.Series.Index ( Index ) import qualified Data.Series.Index as Index import qualified Data.Series.Index.Internal as Index.Internal @@ -60,9 +61,7 @@ infixl 1 `select` -- | \(O(\log n)\). Extract a single value from a series, by key. at :: (Vector v a, Ord k) => Series v k a -> k -> Maybe a -at (MkSeries ks vs) k = do - ix <- Index.lookupIndex k ks - pure $ Vector.unsafeIndex vs ix +at (MkSeries ks vs) k = Index.lookupIndex k ks <&> Vector.unsafeIndex vs {-# INLINABLE at #-} @@ -72,8 +71,8 @@ iat (MkSeries _ vs) = (Vector.!?) vs {-# INLINABLE iat #-} --- | require a series with a new index. --- Contrary to 'select', all keys in @'Set' k@ will be present in the re-indexed series. +-- | Require a series with a new index. +-- Contrary to 'select', all keys in @'Index' k@ will be present in the re-indexed series. require :: (Vector v a, Vector v (Maybe a), Ord k) => Series v k a -> Index k -> Series v k (Maybe a) {-# INLINABLE require #-} @@ -95,7 +94,7 @@ requireWith replacement f xs ss in G.map f (xs `selectSubset` existingKeys) <> MkSeries newKeys (Vector.fromListN (Index.size newKeys) (replacement <$> Index.toAscList newKeys)) --- | Drop the index of a series by replacing it with an @Int@-based index. Values will +-- | \(O(n)\) Drop the index of a series by replacing it with an @Int@-based index. Values will -- be indexed from 0. dropIndex :: Series v k a -> Series v Int a {-# INLINABLE dropIndex #-} @@ -263,6 +262,7 @@ instance Selection Index where -- for large Series in xs `selectSubset` selectedKeys + -- | Selecting a sub-series from a 'Set' is a convenience -- function. Internally, the 'Set' is converted to an index first. instance Selection Set where @@ -287,7 +287,7 @@ instance Selection Range where select series rng = case keysInRange series rng of Nothing -> mempty Just (kstart, kstop) -> let indexOf xs k = Index.Internal.findIndex k (index xs) - in slice (series `indexOf` kstart) (1 + indexOf series kstop) series + in slice (series `indexOf` kstart) (1 + series `indexOf` kstop) series -- | Select a sub-series from a series matching a condition. @@ -312,12 +312,14 @@ selectSubset (MkSeries ks vs) ss -- while filtering away on keys? Initial attempts did not lead -- to performance improvements, but I can't imagine that calling -- `Index.Internal.findIndex` repeatedly is efficient + -- + -- Maybe use Data.Series.Index.indexed to traverse the index once? = MkSeries ss $ Boxed.convert $ Boxed.map (Vector.unsafeIndex vs . (`Index.Internal.findIndex` ks)) $ Index.toAscVector ss --- | Yield a subseries based on indices. The end index is not included. +-- | \(O(\log n)\) Yield a subseries based on integer indices. The end index is not included. slice :: Vector v a => Int -- ^ Start index -> Int -- ^ End index, which is not included @@ -326,6 +328,7 @@ slice :: Vector v a {-# INLINABLE slice #-} slice start stop (MkSeries ks vs) = let stop' = min (Vector.length vs) stop + -- Index.take is O(log n) while Vector.slice is O(1) in MkSeries { index = Index.take (stop' - start) $ Index.drop start ks , values = Vector.slice start (stop' - start) vs } diff --git a/javelin/src/Data/Series/Unboxed.hs b/javelin/src/Data/Series/Unboxed.hs index 69eff3c..f44bbdf 100644 --- a/javelin/src/Data/Series/Unboxed.hs +++ b/javelin/src/Data/Series/Unboxed.hs @@ -667,7 +667,7 @@ require :: (Unbox a, Ord k) require f = G.requireWith f id --- | Drop the index of a series by replacing it with an `Int`-based index. Values will +-- | \(O(n)\) Drop the index of a series by replacing it with an `Int`-based index. Values will -- be indexed from 0. -- -- >>> let xs = Series.fromList [("Paris", 1 :: Int), ("London", 2), ("Lisbon", 4)]