0 | ||| Relaxed Radix Balanced Vectors (RRBVector)
   1 | module Data.RRBVector
   2 |
   3 | import public Data.RRBVector.Internal
   4 |
   5 | import Data.Array
   6 | import Data.Array.Core
   7 | import Data.Array.Index
   8 | import Data.Array.Indexed
   9 | import Data.Bits
  10 | import Data.Linear.Ref1
  11 | import Data.Linear.Traverse1
  12 | import Data.List
  13 | import Data.List1
  14 | import Data.Maybe
  15 | import Data.SnocList
  16 | import Data.Vect
  17 | import Data.Zippable
  18 | import Syntax.T1 as T1
  19 |
  20 | %hide Prelude.null
  21 | %hide Prelude.Ops.infixr.(<|)
  22 | %hide Prelude.Ops.infixl.(|>)
  23 |
  24 | %default total
  25 |
  26 | --------------------------------------------------------------------------------
  27 | --          Fixity
  28 | --------------------------------------------------------------------------------
  29 |
  30 | export
  31 | infixr 5 ><
  32 |
  33 | export
  34 | infixr 5 <|
  35 |
  36 | export
  37 | infixl 5 |>
  38 |
  39 | --------------------------------------------------------------------------------
  40 | --          Utilities
  41 | --------------------------------------------------------------------------------
  42 |
  43 | ||| Transport an indexed array across an equality of its lengths.
  44 | |||
  45 | ||| The equality proof is erased at runtime, so this introduces no runtime
  46 | ||| conversion or allocation.
  47 | |||
  48 | private
  49 | %inline
  50 | castIArray :  {m, n : Nat}
  51 |            -> (0 prf : m = n)
  52 |            -> IArray m a
  53 |            -> IArray n a
  54 | castIArray Refl arr =
  55 |   arr
  56 |
  57 | ||| Reflexivity of `LTE` for natural numbers.
  58 | |||
  59 | ||| This proof is erased at runtime.
  60 | |||
  61 | private
  62 | 0 lteReflNat :  (n : Nat)
  63 |              -> LTE n n
  64 | lteReflNat Z     =
  65 |   LTEZero
  66 | lteReflNat (S n) =
  67 |   LTESucc (lteReflNat n)
  68 |
  69 | ||| Adding one on the right of a natural number is its successor.
  70 | |||
  71 | private
  72 | 0 plusOneRight :  (n : Nat)
  73 |                -> plus n 1 = S n
  74 | plusOneRight Z     =
  75 |   Refl
  76 | plusOneRight (S n) =
  77 |   cong S (plusOneRight n)
  78 |
  79 | ||| Construct a bounded child collection by appending one child to an indexed
  80 | ||| array.
  81 | |||
  82 | ||| The resulting collection is statically nonempty. The equality between
  83 | ||| `n + 1` and `S n` is proved and erased at runtime.
  84 | |||
  85 | private
  86 | childrenSnoc :  {n : Nat}
  87 |              -> IArray n (Tree a)
  88 |              -> Tree a
  89 |              -> Children a
  90 | childrenSnoc {n} xs x =
  91 |   let arr  : IArray (plus n 1) (Tree a)
  92 |       arr  = append xs (fill 1 x)
  93 |       arr' : IArray (S n) (Tree a)
  94 |       arr' = castIArray (plusOneRight n) arr
  95 |     in MkChildren {n = S n} {nonEmpty = LTESucc LTEZero} {withinBlock = believe_me ()} arr'
  96 |
  97 | ||| Construct a bounded child collection by prepending one child to an indexed
  98 | ||| array.
  99 | |||
 100 | ||| The resulting collection is statically nonempty, and the child count is
 101 | ||| carried directly in the resulting `Children`.
 102 | |||
 103 | ||| The branching-factor proof is erased at runtime.
 104 | |||
 105 | private
 106 | childrenCons :  {n : Nat}
 107 |              -> Tree a
 108 |              -> IArray n (Tree a)
 109 |              -> Children a
 110 | childrenCons {n} x xs =
 111 |   MkChildren {n = S n} {nonEmpty = LTESucc LTEZero} {withinBlock = believe_me ()} (append (fill 1 x) xs)
 112 |
 113 | ||| Construct a bounded nonempty child collection from an internal array.
 114 | |||
 115 | ||| Callers must maintain the RRB invariant that the array is nonempty and
 116 | ||| contains no more than `blocksize` children. The branching-factor proof is
 117 | ||| erased at runtime.
 118 | |||
 119 | private
 120 | childrenFromArray :  Array (Tree a)
 121 |                   -> Children a
 122 | childrenFromArray (A Z _) =
 123 |   assert_total (idris_crash "Data.RRBVector.childrenFromArray: empty child array")
 124 | childrenFromArray (A (S n) arr) =
 125 |   MkChildren {nonEmpty = LTESucc LTEZero} {withinBlock = believe_me ()} arr
 126 |
 127 | ||| The final valid index of a statically nonempty collection.
 128 | |||
 129 | private %inline
 130 | lastFin :  {n : Nat}
 131 |         -> Fin (S n)
 132 | lastFin {n = Z} =
 133 |   FZ
 134 | lastFin {n = S k} =
 135 |   FS lastFin
 136 |
 137 | --------------------------------------------------------------------------------
 138 | --          Creating RRB-Vectors
 139 | --------------------------------------------------------------------------------
 140 |
 141 | ||| The empty vector. O(1)
 142 | |||
 143 | export
 144 | empty : RRBVector a
 145 | empty = Empty
 146 |
 147 | ||| A vector with a single element. O(1)
 148 | |||
 149 | export
 150 | singleton :  a
 151 |           -> RRBVector a
 152 | singleton x = Root 1 0 (Leaf $ A 1 $ fill 1 x)
 153 |
 154 | ||| Create a new vector from a list. O(n)
 155 | |||
 156 | ||| Leaf and internal-node arrays are filled from left to right using `Ix`.
 157 | ||| The `Ix remaining n` witness carries the current valid array position, so
 158 | ||| writes require no dynamic `Nat`-to-`Fin` conversion.
 159 | |||
 160 | export
 161 | fromList :
 162 |      List a
 163 |   -> RRBVector a
 164 | fromList []  =
 165 |   Empty
 166 | fromList [x] =
 167 |   singleton x
 168 | fromList xs  =
 169 |   case nodes Leaf xs of
 170 |     [tree] =>
 171 |       Root (treeSize 0 tree) 0 tree
 172 |     xs' =>
 173 |       assert_smaller xs (iterateNodes blockshift xs')
 174 |   where
 175 |     ||| Build leaf-sized nodes from a list.
 176 |     |||
 177 |     ||| `remaining` is the number of writable array positions still available.
 178 |     ||| The `Ix remaining n` witness identifies the current forward position
 179 |     ||| and converts directly to `Fin n` through `ixToFin`.
 180 |     |||
 181 |     nodes :  (Array a -> Tree a)
 182 |           -> List a
 183 |           -> List (Tree a)
 184 |     nodes f trees =
 185 |       let (tree, rest) = unsafeAlloc blocksize (go {n = blocksize} blocksize f trees)
 186 |         in case rest of
 187 |             [] =>
 188 |               [tree]
 189 |             rest' =>
 190 |               tree :: nodes f (assert_smaller trees rest')
 191 |       where
 192 |         ||| Fill one array from left to right.
 193 |         |||
 194 |         ||| When the input list is exhausted before the array is full,
 195 |         ||| `ixToNat pos` is the number of positions that were written.
 196 |         |||
 197 |         ||| When `remaining` reaches zero, the array is full and the
 198 |         ||| unconsumed input list is returned for construction of the next
 199 |         ||| node.
 200 |         |||
 201 |         go :  {n : Nat}
 202 |            -> (remaining : Nat)
 203 |            -> {auto pos : Ix remaining n}
 204 |            -> (Array a -> Tree a)
 205 |            -> List a
 206 |            -> WithMArray n a (Tree a, List a)
 207 |         go {n} remaining {pos} f [] r      = T1.do
 208 |           res <- unsafeFreeze r
 209 |           let written : Nat
 210 |               written = ixToNat pos
 211 |           pure
 212 |             ( f $
 213 |                 force $
 214 |                   take written $
 215 |                     A n res
 216 |             , []
 217 |             )
 218 |         go {n} Z         {pos} f xs        r = T1.do
 219 |           res <- unsafeFreeze r
 220 |           pure
 221 |             ( f $ A n res
 222 |             , xs
 223 |             )
 224 |         go {n} (S k)     {pos} f (x :: xs) r =
 225 |           let idx : Fin n
 226 |               idx = ixToFin pos
 227 |            in T1.do
 228 |                 set r idx x
 229 |                 assert_total (go {n} k {pos = IS pos} f xs r)
 230 |     ||| Build internal RRB nodes from a list of child trees.
 231 |     |||
 232 |     ||| As with `nodes`, array positions are represented by `Ix`, eliminating
 233 |     ||| dynamic `Nat`-to-`Fin` conversion while filling each child array.
 234 |     |||
 235 |     nodes' :  (Array (Tree a) -> Tree a)
 236 |            -> List (Tree a)
 237 |            -> List (Tree a)
 238 |     nodes' f trees =
 239 |       let (tree, rest) =
 240 |             unsafeAlloc blocksize (go {n = blocksize} blocksize f trees)
 241 |        in case rest of
 242 |             [] =>
 243 |               [tree]
 244 |             rest' =>
 245 |               tree :: nodes' f (assert_smaller trees rest')
 246 |       where
 247 |         ||| Fill one internal-node child array from left to right.
 248 |         |||
 249 |         go :  {n : Nat}
 250 |            -> (remaining : Nat)
 251 |            -> {auto pos : Ix remaining n}
 252 |            -> (Array (Tree a) -> Tree a)
 253 |            -> List (Tree a)
 254 |            -> WithMArray n (Tree a) (Tree a, List (Tree a))
 255 |         go {n} remaining {pos} f []        r = T1.do
 256 |           res <- unsafeFreeze r
 257 |           let written : Nat
 258 |               written = ixToNat pos
 259 |           pure
 260 |             ( f $
 261 |                 force $
 262 |                   take written $
 263 |                     A n res
 264 |             , []
 265 |             )
 266 |         go {n} Z         {pos} f xs        r = T1.do
 267 |           res <- unsafeFreeze r
 268 |           pure
 269 |             ( f $ A n res
 270 |             , xs
 271 |             )
 272 |         go {n} (S k)     {pos} f (x :: xs) r =
 273 |           let idx : Fin n
 274 |               idx = ixToFin pos
 275 |            in T1.do
 276 |                 set r idx x
 277 |                 assert_total (go {n} k {pos = IS pos} f xs r)
 278 |     ||| Repeatedly group child trees into balanced internal nodes until only a
 279 |     ||| single root remains.
 280 |     |||
 281 |     iterateNodes :  Shift
 282 |                  -> List (Tree a)
 283 |                  -> RRBVector a
 284 |     iterateNodes sh trees =
 285 |       case nodes' (\arr => Balanced (childrenFromArray arr)) trees of
 286 |         [tree] =>
 287 |           Root (treeSize sh tree) sh tree
 288 |         trees' =>
 289 |           iterateNodes (up sh) (assert_smaller trees trees')
 290 |
 291 | ||| Creates a vector of length `n` with every element set to `x`. O(log n)
 292 | |||
 293 | export
 294 | replicate :  Nat
 295 |           -> a
 296 |           -> RRBVector a
 297 | replicate n x =
 298 |   case compare n 0 of
 299 |     LT =>
 300 |       Empty
 301 |     EQ =>
 302 |       Empty
 303 |     GT =>
 304 |       case compare n blocksize of
 305 |         LT =>
 306 |           Root n 0 (Leaf $ A n $ fill n x)
 307 |         EQ =>
 308 |           Root n 0 (Leaf $ A n $ fill n x)
 309 |         GT =>
 310 |           let size' = integerToNat $ (natToInteger $ minus n 1) .&. (natToInteger $ plus blockmask 1)
 311 |             in iterateNodes blockshift (Leaf $ A blocksize $ fill blocksize x) (Leaf $ A size' $ fill size' x)
 312 |   where
 313 |     iterateNodes :  Shift
 314 |                  -> Tree a
 315 |                  -> Tree a
 316 |                  -> RRBVector a
 317 |     iterateNodes sh full rest =
 318 |       let subtreesm1   = (natToInteger $ minus n 1) `shiftR` sh
 319 |           restsize     = integerToNat $ subtreesm1 .&. natToInteger blockmask
 320 |           restchildren : Children a
 321 |           restchildren = childrenSnoc (fill restsize full) rest
 322 |           rest'        : Tree a
 323 |           rest'        = Balanced restchildren
 324 |        in case compare subtreesm1 (natToInteger blocksize) of
 325 |             LT =>
 326 |               Root n sh rest'
 327 |             EQ =>
 328 |               let fullchildren : Children a
 329 |                   fullchildren = MkChildren {n = blocksize} {nonEmpty = believe_me ()} {withinBlock = lteReflNat blocksize} (fill blocksize full)
 330 |                   full'        = Balanced fullchildren
 331 |                 in iterateNodes (up sh) (assert_smaller full full') (assert_smaller rest rest')
 332 |             GT =>
 333 |               let fullchildren : Children a
 334 |                   fullchildren = MkChildren {n = blocksize} {nonEmpty = believe_me ()} {withinBlock = lteReflNat blocksize} (fill blocksize full)
 335 |                   full'        = Balanced fullchildren
 336 |                 in iterateNodes (up sh) (assert_smaller full full') (assert_smaller rest rest')
 337 |
 338 | --------------------------------------------------------------------------------
 339 | --          Creating Lists from RRB-Vectors
 340 | --------------------------------------------------------------------------------
 341 |
 342 | ||| Convert a vector to a list. O(n)
 343 | |||
 344 | export
 345 | toList :  RRBVector a
 346 |        -> List a
 347 | toList Empty           =
 348 |   []
 349 | toList (Root _ _ tree) =
 350 |   treeToList tree
 351 |   where
 352 |     treeToList :  Tree a
 353 |                -> List a
 354 |     treeToList (Balanced (MkChildren {n} trees))            =
 355 |       assert_total (concat (map treeToList (toList (A n trees))))
 356 |     treeToList (Unbalanced (MkRelaxedChildren {n} trees _)) =
 357 |       assert_total (concat (map treeToList (toList (A n trees))))
 358 |     treeToList (Leaf arr)                                   =
 359 |       toList arr
 360 |
 361 | --------------------------------------------------------------------------------
 362 | --          Folds
 363 | --------------------------------------------------------------------------------
 364 |
 365 | export
 366 | foldl :  (b -> a -> b)
 367 |       -> b
 368 |       -> RRBVector a
 369 |       -> b
 370 | foldl f acc = go
 371 |   where
 372 |     foldlTree :  b
 373 |               -> Tree a
 374 |               -> b
 375 |     foldlTree acc' (Balanced (MkChildren {n} trees))            =
 376 |       assert_total (foldl foldlTree acc' (A n trees))
 377 |     foldlTree acc' (Unbalanced (MkRelaxedChildren {n} trees _)) =
 378 |       assert_total (foldl foldlTree acc' (A n trees))
 379 |     foldlTree acc' (Leaf arr)                                   =
 380 |       assert_total (foldl f acc' arr)
 381 |     go :  RRBVector a
 382 |        -> b
 383 |     go Empty           =
 384 |       acc
 385 |     go (Root _ _ tree) =
 386 |       assert_total (foldlTree acc tree)
 387 |
 388 | export
 389 | foldr :  (a -> b -> b)
 390 |       -> b
 391 |       -> RRBVector a
 392 |       -> b
 393 | foldr f acc = go
 394 |   where
 395 |     foldrTree :  Tree a
 396 |               -> b
 397 |               -> b
 398 |     foldrTree (Balanced (MkChildren {n} trees))            acc' =
 399 |       assert_total (foldr foldrTree acc' (A n trees))
 400 |     foldrTree (Unbalanced (MkRelaxedChildren {n} trees _)) acc' =
 401 |       assert_total (foldr foldrTree acc' (A n trees))
 402 |     foldrTree (Leaf arr)                                   acc' =
 403 |       assert_total (foldr f acc' arr)
 404 |     go :  RRBVector a
 405 |        -> b
 406 |     go Empty           =
 407 |       acc
 408 |     go (Root _ _ tree) =
 409 |       assert_total (foldrTree tree acc)
 410 |
 411 | --------------------------------------------------------------------------------
 412 | --          Query
 413 | --------------------------------------------------------------------------------
 414 |
 415 | ||| Is the vector empty? O(1)
 416 | |||
 417 | export
 418 | null :  RRBVector a
 419 |      -> Bool
 420 | null Empty = True
 421 | null _     = False
 422 |
 423 | ||| Return the size of a vector. O(1)
 424 | |||
 425 | export
 426 | length :  RRBVector a
 427 |        -> Nat
 428 | length Empty        = 0
 429 | length (Root s _ _) = s
 430 |
 431 | --------------------------------------------------------------------------------
 432 | --          Indexing
 433 | --------------------------------------------------------------------------------
 434 |
 435 | ||| The element at the index or `Nothing` if the index is out of range. O(log n)
 436 | |||
 437 | export
 438 | lookup :  Nat
 439 |        -> RRBVector a
 440 |        -> Maybe a
 441 | lookup _ Empty               =
 442 |   Nothing
 443 | lookup i (Root size sh tree) =
 444 |   case i < size of
 445 |     False =>
 446 |       Nothing
 447 |     True =>
 448 |       Just (lookupTree i sh tree)
 449 |   where
 450 |     lookupTree :  Nat
 451 |                -> Shift
 452 |                -> Tree a
 453 |                -> a
 454 |     lookupTree i sh (Balanced (MkChildren {n} children))                           =
 455 |       let childidx : Nat
 456 |           childidx = radixIndex i sh
 457 |           0 childLT : LT childidx n
 458 |           childLT = believe_me ()
 459 |           child : Fin n
 460 |           child = natToFinLT childidx @{childLT}
 461 |         in assert_total (lookupTree i (down sh) (at children child))
 462 |     lookupTree i sh (Unbalanced (MkRelaxedChildren {n} {nonEmpty} children sizes)) =
 463 |       let MkRelaxedIndex child offset = relaxedRadixIndex {n} {nonEmpty} sizes i sh
 464 |         in assert_total (lookupTree offset (down sh) (at children child))
 465 |     lookupTree i _  (Leaf (A n elems))                                             =
 466 |       let leafidx  : Nat
 467 |           leafidx  = integerToNat ((natToInteger i) .&. natToInteger blockmask)
 468 |           0 leafLT : LT leafidx n
 469 |           leafLT   = believe_me ()
 470 |         in atNat elems leafidx @{leafLT}
 471 |
 472 | ||| A flipped version of lookup. O(log n)
 473 | |||
 474 | export
 475 | (!?) :  RRBVector a
 476 |      -> Nat
 477 |      -> Maybe a
 478 | (!?) = flip lookup
 479 |
 480 | ||| Update the element at the index with a new element.
 481 | |||
 482 | ||| If the index is out of range, the original vector is returned. O(log n)
 483 | |||
 484 | export
 485 | update :  Nat
 486 |        -> a
 487 |        -> RRBVector a
 488 |        -> RRBVector a
 489 | update _ _ Empty                 =
 490 |   Empty
 491 | update i x v@(Root size sh tree) =
 492 |   case i < size of
 493 |     False =>
 494 |       v
 495 |     True =>
 496 |       Root size sh (updateTree i sh tree)
 497 |   where
 498 |     updateTree :  Nat
 499 |                -> Shift
 500 |                -> Tree a
 501 |                -> Tree a
 502 |     updateTree i sh (Balanced (MkChildren {n} {nonEmpty} {withinBlock} children))                =
 503 |       let childidx  : Nat
 504 |           childidx  = radixIndex i sh
 505 |           0 childLT : LT childidx n
 506 |           childLT   = believe_me ()
 507 |           child     : Fin n
 508 |           child     = natToFinLT childidx @{childLT}
 509 |           children' = updateAt child (updateTree i (down sh)) children
 510 |         in assert_total (Balanced (MkChildren {nonEmpty = nonEmpty} {withinBlock = withinBlock} children'))
 511 |     updateTree i sh (Unbalanced (MkRelaxedChildren {n} {nonEmpty} {withinBlock} children sizes)) =
 512 |       let MkRelaxedIndex child offset = relaxedRadixIndex {n} {nonEmpty} sizes i sh
 513 |           children'                   = updateAt child (updateTree offset (down sh)) children
 514 |         in assert_total (Unbalanced (MkRelaxedChildren {nonEmpty = nonEmpty} {withinBlock = withinBlock} children' sizes))
 515 |     updateTree i _  (Leaf (A n elems))                                                           =
 516 |       let leafidx  : Nat
 517 |           leafidx  = integerToNat ((natToInteger i) .&. natToInteger blockmask)
 518 |           0 leafLT : LT leafIdx n
 519 |           leafLT   = believe_me ()
 520 |           idx      : Fin n
 521 |           idx      = natToFinLT leafidx @{leafLT}
 522 |         in Leaf (A n (setAt idx x elems))
 523 |
 524 | ||| Adjust the element at the index by applying the function to it.
 525 | |||
 526 | ||| If the index is out of range, the original vector is returned. O(log n)
 527 | |||
 528 | export
 529 | adjust :  Nat
 530 |        -> (a -> a)
 531 |        -> RRBVector a
 532 |        -> RRBVector a
 533 | adjust _ _ Empty                 =
 534 |   Empty
 535 | adjust i f v@(Root size sh tree) =
 536 |   case i < size of
 537 |     False =>
 538 |       v
 539 |     True  =>
 540 |       Root size sh (adjustTree i sh tree)
 541 |   where
 542 |     adjustTree :  Nat
 543 |                -> Shift
 544 |                -> Tree a
 545 |                -> Tree a
 546 |     adjustTree i sh (Balanced (MkChildren {n} {nonEmpty} {withinBlock} children))                =
 547 |       let childidx  : Nat
 548 |           childidx  = radixIndex i sh
 549 |           0 childLT : LT childidx n
 550 |           childLT   = believe_me ()
 551 |           child     : Fin n
 552 |           child     = natToFinLT childidx @{childLT}
 553 |           children' = updateAt child (adjustTree i (down sh)) children
 554 |         in assert_total (Balanced (MkChildren {nonEmpty = nonEmpty} {withinBlock = withinBlock} children'))
 555 |     adjustTree i sh (Unbalanced (MkRelaxedChildren {n} {nonEmpty} {withinBlock} children sizes)) =
 556 |       let MkRelaxedIndex child offset = relaxedRadixIndex {n} {nonEmpty} sizes i sh
 557 |           children'                   = updateAt child (adjustTree offset (down sh)) children
 558 |         in assert_total (Unbalanced (MkRelaxedChildren {nonEmpty = nonEmpty} {withinBlock = withinBlock} children' sizes))
 559 |     adjustTree i _  (Leaf (A n elems))                                                           =
 560 |       let leafidx  : Nat
 561 |           leafidx  = integerToNat ((natToInteger i) .&. natToInteger blockmask)
 562 |           0 leafLT : LT leafidx n
 563 |           leafLT   = believe_me ()
 564 |           idx      : Fin n
 565 |           idx      = natToFinLT leafidx @{leafLT}
 566 |         in Leaf (A n (updateAt idx f elems))
 567 |
 568 | private
 569 | normalize :  RRBVector a
 570 |           -> RRBVector a
 571 | normalize (Root size sh (Balanced (MkChildren {n = 1} children)))            =
 572 |   assert_total (normalize (Root size (down sh) (at children FZ)))
 573 | normalize (Root size sh (Unbalanced (MkRelaxedChildren {n = 1} children _))) =
 574 |   assert_total (normalize (Root size (down sh) (at children FZ)))
 575 | normalize v =
 576 |   v
 577 |
 578 | ||| Retain the portion of a tree ending at logical index `i`.
 579 | |||
 580 | ||| `i` is the index of the final element retained in the resulting tree.
 581 | |||
 582 | ||| Internal child positions are derived from the RRB indexing rules and
 583 | ||| represented with erased bounds proofs. No dynamic `Nat`-to-`Fin`
 584 | ||| conversion is required.
 585 | |||
 586 | private
 587 | takeTree :  Nat
 588 |          -> Shift
 589 |          -> Tree a
 590 |          -> Tree a
 591 | takeTree i sh (Balanced (MkChildren {n} children))                           =
 592 |   let childidx  : Nat
 593 |       childidx  = radixIndex i sh
 594 |       0 childLT : LT childidx n
 595 |       childLT   = believe_me ()
 596 |       prefix'   : IArray (S childidx) (Tree a)
 597 |       prefix'   = force (take (S childidx) children @{childLT})
 598 |       prefix''  : IArray (S childidx) (Tree a)
 599 |       prefix''  = updateAt (lastFin {n = childidx}) (takeTree i (down sh)) prefix'
 600 |     in assert_total (Balanced (MkChildren {n = S childidx} {nonEmpty = LTESucc LTEZero} {withinBlock = believe_me ()} prefix''))
 601 | takeTree i sh (Unbalanced (MkRelaxedChildren {n} {nonEmpty} children sizes)) =
 602 |   let MkRelaxedIndex child subidx = relaxedRadixIndex {n} {nonEmpty} sizes i sh
 603 |       childidx    : Nat
 604 |       childidx    = finToNat child
 605 |       0 prefixLTE : LTE (S childidx) n
 606 |       prefixLTE   = believe_me ()
 607 |       prefix'     : IArray (S childidx) (Tree a)
 608 |       prefix'     = force (take (S childidx) children @{prefixLTE})
 609 |       prefix''    : IArray (S childidx) (Tree a)
 610 |       prefix''    = updateAt (lastFin {n = childidx}) (takeTree subidx (down sh)) prefix'
 611 |       bounded     : Children a
 612 |       bounded     = MkChildren {n = S childidx} {nonEmpty = LTESucc LTEZero} {withinBlock = believe_me ()} prefix''
 613 |     in assert_total (computeSizes sh bounded)
 614 | takeTree i _  (Leaf (A n elems))                                             =
 615 |   let leafidx    : Nat
 616 |       leafidx    = integerToNat ((natToInteger i) .&. natToInteger blockmask)
 617 |       count      : Nat
 618 |       count      = S leafidx
 619 |       0 countLTE : LTE count n
 620 |       countLTE   = believe_me ()
 621 |       elems'     : IArray count a
 622 |       elems'     = force (take count elems @{countLTE})
 623 |     in Leaf (A count elems')
 624 |
 625 | ||| Remove the first `n` logical elements from a tree.
 626 | |||
 627 | ||| The selected child becomes the first child in the resulting node and is
 628 | ||| recursively trimmed by the offset within that child.
 629 | |||
 630 | ||| Since this function is called only when elements remain after the drop,
 631 | ||| every resulting internal node is nonempty. Array positions therefore use
 632 | ||| erased bounds evidence rather than dynamic `Nat`-to-`Fin` conversion.
 633 | |||
 634 | private
 635 | dropTree :  Nat
 636 |          -> Shift
 637 |          -> Tree a
 638 |          -> Tree a
 639 | dropTree i sh (Balanced (MkChildren {n} children))                           =
 640 |   let childidx            : Nat
 641 |       childidx            = radixIndex i sh
 642 |       remaining           : Nat
 643 |       remaining           = minus n childidx
 644 |       children'           : IArray remaining (Tree a)
 645 |       children'           = force (drop childidx children)
 646 |       0 remainingpositive : LT 0 remaining
 647 |       remainingpositive   = believe_me ()
 648 |       zero                : Fin remaining
 649 |       zero                = natToFinLT 0 @{remainingpositive}
 650 |       children''          : IArray remaining (Tree a)
 651 |       children''          = updateAt zero (dropTree i (down sh)) children'
 652 |       bounded             : Children a
 653 |       bounded             = MkChildren {n = remaining} {nonEmpty = remainingpositive} {withinBlock = believe_me ()} children''
 654 |     in assert_total (computeSizes sh bounded)
 655 | dropTree i sh (Unbalanced (MkRelaxedChildren {n} {nonEmpty} children sizes)) =
 656 |   let MkRelaxedIndex child subidx = relaxedRadixIndex {n} {nonEmpty} sizes i sh
 657 |       childidx                    : Nat
 658 |       childidx                    = finToNat child
 659 |       remaining                   : Nat
 660 |       remaining                   = minus n childidx
 661 |       children'                   : IArray remaining (Tree a)
 662 |       children'                   = force (drop childidx children)
 663 |       0 remainingpositive         : LT 0 remaining
 664 |       remainingpositive           = believe_me ()
 665 |       zero                        : Fin remaining
 666 |       zero                        = natToFinLT 0 @{remainingpositive}
 667 |       children''                  : IArray remaining (Tree a)
 668 |       children''                  = updateAt zero (dropTree subidx (down sh)) children'
 669 |       bounded                     : Children a
 670 |       bounded                     = MkChildren {n = remaining} {nonEmpty = remainingpositive} {withinBlock = believe_me ()} children''
 671 |     in assert_total (computeSizes sh bounded)
 672 | dropTree i _  (Leaf (A n elems))                                             =
 673 |   let offset    : Nat
 674 |       offset    = integerToNat ((natToInteger i) .&. natToInteger blockmask)
 675 |       remaining : Nat
 676 |       remaining = minus n offset
 677 |       elems'    : IArray remaining a
 678 |       elems'    = force (drop offset elems)
 679 |     in Leaf (A remaining elems')
 680 |
 681 | ||| The first i elements of the vector.
 682 | ||| If the vector contains less than or equal to i elements, the whole vector is returned. O(log n)
 683 | |||
 684 | export
 685 | take :  Nat
 686 |      -> RRBVector a
 687 |      -> RRBVector a
 688 | take _ Empty                 =
 689 |   empty
 690 | take n v@(Root size sh tree) =
 691 |   case compare n 0 of
 692 |     LT =>
 693 |       empty
 694 |     EQ =>
 695 |       empty
 696 |     GT =>
 697 |       case compare n size of
 698 |         LT =>
 699 |           normalize $ Root n sh (takeTree (minus n 1) sh tree)
 700 |         EQ =>
 701 |           v
 702 |         GT =>
 703 |           v
 704 |
 705 | ||| The vector without the first i elements.
 706 | ||| If the vector contains less than or equal to i elements, the empty vector is returned. O(log n)
 707 | |||
 708 | export
 709 | drop :  Nat
 710 |      -> RRBVector a
 711 |      -> RRBVector a
 712 | drop _ Empty                 =
 713 |   empty
 714 | drop n v@(Root size sh tree) =
 715 |   case compare n 0 of
 716 |     LT =>
 717 |       v
 718 |     EQ =>
 719 |       v
 720 |     GT =>
 721 |       case compare n size of
 722 |         LT =>
 723 |           normalize $ Root (minus size n) sh (dropTree n sh tree)
 724 |         EQ =>
 725 |           empty
 726 |         GT =>
 727 |           empty
 728 |
 729 | ||| Split the vector at the given index. O(log n)
 730 | |||
 731 | export
 732 | splitAt :  Nat
 733 |         -> RRBVector a
 734 |         -> (RRBVector a, RRBVector a)
 735 | splitAt _ Empty                 = (Empty, Empty)
 736 | splitAt n v@(Root size sh tree) =
 737 |   case compare n 0 of
 738 |     LT =>
 739 |       (empty, v)
 740 |     EQ =>
 741 |       (empty, v)
 742 |     GT =>
 743 |       case compare n size of
 744 |         LT =>
 745 |           let left  = normalize $ Root n sh (takeTree (minus n 1) sh tree)
 746 |               right = normalize $ Root (minus size n) sh (dropTree n sh tree)
 747 |             in (left, right)
 748 |         EQ =>
 749 |           (v, empty)
 750 |         GT =>
 751 |           (v, empty)
 752 |
 753 | --------------------------------------------------------------------------------
 754 | --          Deconstruction
 755 | --------------------------------------------------------------------------------
 756 |
 757 | ||| The first element and the vector without the first element, or `Nothing` if the vector is empty. O(log n)
 758 | |||
 759 | export
 760 | viewl :  RRBVector a
 761 |       -> Maybe (a, RRBVector a)
 762 | viewl Empty             =
 763 |   Nothing
 764 | viewl v@(Root _ _ tree) =
 765 |   let tail = drop 1 v
 766 |     in Just ( headTree tree
 767 |             , tail
 768 |             )
 769 |   where
 770 |     headTree :  Tree a
 771 |              -> a
 772 |     headTree (Balanced (MkChildren {n = S k} children))            =
 773 |       assert_total (headTree (at children FZ))
 774 |     headTree (Unbalanced (MkRelaxedChildren {n = S k} children _)) =
 775 |       assert_total (headTree (at children FZ))
 776 |     headTree (Leaf (A Z _))                                        =
 777 |       assert_total (idris_crash "Data.RRBVector.viewl: empty leaf")
 778 |     headTree (Leaf (A (S k) elems))                                =
 779 |       at elems FZ
 780 |
 781 | ||| The vector without the last element and the last element, or `Nothing` if the vector is empty. O(log n)
 782 | |||
 783 | export
 784 | viewr :  RRBVector a
 785 |       -> Maybe (RRBVector a, a)
 786 | viewr Empty                =
 787 |   Nothing
 788 | viewr v@(Root size _ tree) =
 789 |   let init = take (minus size 1) v
 790 |     in Just ( init
 791 |             , lastTree tree
 792 |             )
 793 |   where
 794 |     lastTree :  Tree a
 795 |              -> a
 796 |     lastTree (Balanced (MkChildren {n = S k} children))            =
 797 |       assert_total (lastTree (at children lastFin))
 798 |     lastTree (Unbalanced (MkRelaxedChildren {n = S k} children _)) =
 799 |       assert_total (lastTree (at children lastFin))
 800 |     lastTree (Leaf (A Z _))                                        =
 801 |       assert_total (idris_crash "Data.RRBVector.viewr: empty leaf")
 802 |     lastTree (Leaf (A (S k) elems))                                =
 803 |       at elems lastFin
 804 |
 805 | --------------------------------------------------------------------------------
 806 | --          Transformation
 807 | --------------------------------------------------------------------------------
 808 |
 809 | ||| Apply the function to every element. O(n)
 810 | |||
 811 | export
 812 | map :  (a -> b)
 813 |     -> RRBVector a
 814 |     -> RRBVector b
 815 | map _ Empty               =
 816 |   Empty
 817 | map f (Root size sh tree) =
 818 |   Root size sh (mapTree tree)
 819 |   where
 820 |     mapTree :  Tree a
 821 |             -> Tree b
 822 |     mapTree (Balanced (MkChildren {n} {nonEmpty} {withinBlock} children))                =
 823 |       assert_total (Balanced (MkChildren {n} {nonEmpty = nonEmpty} {withinBlock = withinBlock} (map mapTree children)))
 824 |     mapTree (Unbalanced (MkRelaxedChildren {n} {nonEmpty} {withinBlock} children sizes)) =
 825 |       assert_total (Unbalanced (MkRelaxedChildren {n} {nonEmpty = nonEmpty} {withinBlock = withinBlock} (map mapTree children) sizes))
 826 |     mapTree (Leaf arr)                                                                   =
 827 |       Leaf (map f arr)
 828 |
 829 | ||| Reverse the vector. O(n)
 830 | |||
 831 | export
 832 | reverse :  RRBVector a
 833 |         -> RRBVector a
 834 | reverse v =
 835 |   case compare (length v) 1 of
 836 |     LT =>
 837 |       v
 838 |     EQ =>
 839 |       v
 840 |     GT =>
 841 |       case fromList $ toList v of
 842 |         Nothing =>
 843 |           assert_total $ idris_crash "Data.RRBVector.reverse: can't convert to List1"
 844 |         Just v' =>
 845 |           fromList $ forget $ reverse v'
 846 |
 847 | ||| Take two vectors and return a vector of corresponding pairs.
 848 | ||| If one input is longer, excess elements are discarded from the right end. O(min(n1,n2))
 849 | |||
 850 | export
 851 | zip :  RRBVector a
 852 |     -> RRBVector b
 853 |     -> RRBVector (a, b)
 854 | zip v1 v2 =
 855 |   case fromList $ toList v1 of
 856 |     Nothing  =>
 857 |       assert_total $ idris_crash "Data.RRBVector.zip: can't convert to List1"
 858 |     Just v1' =>
 859 |       case fromList $ toList v2 of
 860 |         Nothing  =>
 861 |           assert_total $ idris_crash "Data.RRBVector.zip: can't convert to List1"
 862 |         Just v2' =>
 863 |           fromList $ forget $ zip v1' v2'
 864 |
 865 | --------------------------------------------------------------------------------
 866 | --          Concatenation
 867 | --------------------------------------------------------------------------------
 868 |
 869 | ||| Create a new single-child branch with shift `sh`.
 870 | |||
 871 | private
 872 | newBranch :  a
 873 |           -> Shift
 874 |           -> Tree a
 875 | newBranch x Z  =
 876 |   Leaf (singleton x)
 877 | newBranch x sh =
 878 |   assert_total (Balanced (MkChildren {n = 1} {nonEmpty = LTESucc LTEZero} {withinBlock = believe_me ()} (fill 1 (newBranch x (down sh)))))
 879 |
 880 | ||| Add an element to the left end of the vector. O(log n)
 881 | |||
 882 | export
 883 | (<|) :  a
 884 |      -> RRBVector a
 885 |      -> RRBVector a
 886 | x <| Empty             =
 887 |   singleton x
 888 | x <| Root size sh tree =
 889 |   case compare insertshift sh of
 890 |     LT =>
 891 |       Root (S size) sh (consTree sh tree)
 892 |     EQ =>
 893 |       Root (S size) sh (consTree sh tree)
 894 |     GT =>
 895 |       let children : IArray 2 (Tree a)
 896 |           children =
 897 |             array ( fromList
 898 |                       [ newBranch x sh
 899 |                       , tree
 900 |                       ]
 901 |                   )
 902 |           rootChildren : Children a
 903 |           rootChildren =
 904 |             MkChildren {n = 2} {nonEmpty = believe_me ()} {withinBlock = believe_me ()} children
 905 |         in Root (S size) insertshift (computeSizes insertshift rootChildren)
 906 |   where
 907 |     ||| Compute the shift at which the new branch must be inserted.
 908 |     |||
 909 |     computeShift :  Nat
 910 |                  -> Shift
 911 |                  -> Shift
 912 |                  -> Tree a
 913 |                  -> Shift
 914 |     computeShift sz sh min (Balanced _)                                             =
 915 |       let hishift  =
 916 |             let comp = mult (log2 (minus sz 1) `div` blockshift) blockshift
 917 |               in case compare comp 0 of
 918 |                    LT =>
 919 |                      0
 920 |                    EQ =>
 921 |                      0
 922 |                    GT =>
 923 |                      comp
 924 |           hi       = (natToInteger $ minus sz 1) `shiftR` hishift
 925 |           newshift = case compare hi (natToInteger blockmask) of
 926 |                        LT =>
 927 |                          hishift
 928 |                        EQ =>
 929 |                          plus hishift blockshift
 930 |                        GT =>
 931 |                          plus hishift blockshift
 932 |         in case compare newshift sh of
 933 |              LT =>
 934 |                newshift
 935 |              EQ =>
 936 |                newshift
 937 |              GT =>
 938 |                min
 939 |     computeShift _ sh min (Unbalanced (MkRelaxedChildren {n = S k} children sizes)) =
 940 |       let sz'     : Nat
 941 |           sz'     = at sizes FZ
 942 |           newtree : Tree a
 943 |           newtree = at children FZ
 944 |           newmin  : Shift
 945 |           newmin  = case compare (S k) blocksize of
 946 |                       LT =>
 947 |                         sh
 948 |                       EQ =>
 949 |                         min
 950 |                       GT =>
 951 |                         min
 952 |         in assert_total (computeShift sz' (down sh) newmin newtree)
 953 |     computeShift _ _ min (Leaf arr) =
 954 |       case compare arr.size blocksize of
 955 |         LT =>
 956 |           0
 957 |         EQ =>
 958 |           min
 959 |         GT =>
 960 |           min
 961 |     insertshift : Shift
 962 |     insertshift = computeShift size sh (up sh) tree
 963 |     consTree :  Shift
 964 |              -> Tree a
 965 |              -> Tree a
 966 |     consTree sh (Balanced (MkChildren {n = S k} {nonEmpty} {withinBlock} children))            =
 967 |       case compare sh insertshift of
 968 |         LT =>
 969 |           assert_total (computeSizes sh (MkChildren {n = S k} {nonEmpty = nonEmpty} {withinBlock = withinBlock} (updateAt FZ (consTree $ down sh) children)))
 970 |         EQ =>
 971 |           let children' = append (fill 1 (newBranch x $ down sh)) children
 972 |             in computeSizes sh (MkChildren {n = S (S k)} {nonEmpty = believe_me ()} {withinBlock = believe_me ()} children')
 973 |         GT =>
 974 |           assert_total (computeSizes sh (MkChildren {n = S k} {nonEmpty = nonEmpty} {withinBlock = withinBlock} (updateAt FZ (consTree $ down sh) children)))
 975 |     consTree sh (Unbalanced (MkRelaxedChildren {n = S k} {nonEmpty} {withinBlock} children _)) =
 976 |       case compare sh insertshift of
 977 |         LT =>
 978 |           assert_total (computeSizes sh (MkChildren {n = S k} {nonEmpty = nonEmpty} {withinBlock = withinBlock} (updateAt FZ (consTree $ down sh) children)))
 979 |         EQ =>
 980 |           let children' = append (fill 1 (newBranch x $ down sh)) children
 981 |             in computeSizes sh (MkChildren {n = S (S k)} {nonEmpty = believe_me ()} {withinBlock = believe_me ()} children')
 982 |         GT =>
 983 |           assert_total (computeSizes sh (MkChildren {n = S k} {nonEmpty = nonEmpty} {withinBlock = withinBlock} (updateAt FZ (consTree $ down sh) children)))
 984 |     consTree _ (Leaf arr)                                                                      =
 985 |       Leaf (A (S arr.size) (append (fill 1 x) arr.arr))
 986 |
 987 | ||| Add an element to the right end of the vector. O(log n)
 988 | |||
 989 | export
 990 | (|>) :  RRBVector a
 991 |      -> a
 992 |      -> RRBVector a
 993 | Empty |> x =
 994 |   singleton x
 995 | Root size sh tree |> x =
 996 |   case compare insertshift sh of
 997 |     LT =>
 998 |       Root (S size) sh (snocTree sh tree)
 999 |     EQ =>
1000 |       Root (S size) sh (snocTree sh tree)
1001 |     GT =>
1002 |       let children     : IArray 2 (Tree a)
1003 |           children     = array ( fromList
1004 |                                    [ tree
1005 |                                    , newBranch x sh
1006 |                                    ]
1007 |                                )
1008 |           rootChildren : Children a
1009 |           rootChildren = MkChildren {n = 2} {nonEmpty = believe_me ()} {withinBlock = believe_me ()} children
1010 |         in Root (S size) insertshift (computeSizes insertshift rootChildren)
1011 |   where
1012 |     ||| Compute the shift at which the new right-hand branch must be inserted.
1013 |     |||
1014 |     computeShift :  Nat
1015 |                  -> Shift
1016 |                  -> Shift
1017 |                  -> Tree a
1018 |                  -> Shift
1019 |     computeShift sz sh min (Balanced _)                                                  =
1020 |       let newshift = mult (countTrailingZeros sz `div` blockshift) blockshift
1021 |         in case compare newshift sh of
1022 |              LT =>
1023 |                newshift
1024 |              EQ =>
1025 |                newshift
1026 |              GT =>
1027 |                min
1028 |     computeShift _  sh min (Unbalanced (MkRelaxedChildren {n = 1} children sizes))       =
1029 |       let sz' : Nat
1030 |           sz' = lastAt sizes
1031 |           newtree : Tree a
1032 |           newtree = lastAt children
1033 |           newmin : Shift
1034 |           newmin = case compare 1 blocksize of
1035 |                      LT =>
1036 |                        sh
1037 |                      EQ =>
1038 |                        min
1039 |                      GT =>
1040 |                        min
1041 |         in assert_total (computeShift sz' (down sh) newmin newtree)
1042 |     computeShift _  sh min (Unbalanced (MkRelaxedChildren {n = S (S k)} children sizes)) =
1043 |       let totalsize   : Nat
1044 |           totalsize   = lastAt sizes
1045 |           previousidx : Fin (S (S k))
1046 |           previousidx = weaken (lastFin {n = k})
1047 |           previous    : Nat
1048 |           previous    = at sizes previousidx
1049 |           sz'         : Nat
1050 |           sz'         = minus totalsize previous
1051 |           newtree     : Tree a
1052 |           newtree     = lastAt children
1053 |           newmin      : Shift
1054 |           newmin      = case compare (S (S k)) blocksize of
1055 |                           LT =>
1056 |                             sh
1057 |                           EQ =>
1058 |                             min
1059 |                           GT =>
1060 |                             min
1061 |         in assert_total (computeShift sz' (down sh) newmin newtree)
1062 |     computeShift _  _  min (Leaf arr)                                                    =
1063 |       case compare arr.size blocksize of
1064 |         LT =>
1065 |           0
1066 |         EQ =>
1067 |           min
1068 |         GT =>
1069 |           min
1070 |     insertshift : Shift
1071 |     insertshift = computeShift size sh (up sh) tree
1072 |     snocTree :  Shift
1073 |              -> Tree a
1074 |              -> Tree a
1075 |     snocTree sh (Balanced (MkChildren {n = S k} {nonEmpty} {withinBlock} children))                =
1076 |       case compare sh insertshift of
1077 |         LT =>
1078 |           assert_total (Balanced (MkChildren {n = S k} {nonEmpty = nonEmpty} {withinBlock = withinBlock} (updateAt lastFin (snocTree $ down sh) children)))
1079 |         EQ =>
1080 |           let children' = append children (fill 1 (newBranch x (down sh)))
1081 |             in Balanced (MkChildren {n = plus (S k) 1} {nonEmpty = believe_me ()} {withinBlock = believe_me ()} children')
1082 |         GT =>
1083 |           assert_total (Balanced (MkChildren {n = S k} {nonEmpty = nonEmpty} {withinBlock = withinBlock} (updateAt lastFin (snocTree $ down sh) children)))
1084 |     snocTree sh (Unbalanced (MkRelaxedChildren {n = S k} {nonEmpty} {withinBlock} children sizes)) =
1085 |       case compare sh insertshift of
1086 |         LT =>
1087 |           let lastsize : Nat
1088 |               lastsize = plus (lastAt sizes) 1
1089 |             in assert_total (Unbalanced (MkRelaxedChildren {n = S k} {nonEmpty = nonEmpty} {withinBlock = withinBlock} (updateAt lastFin (snocTree $ down sh) children) (setAt lastFin lastsize sizes)))
1090 |         EQ =>
1091 |           let lastsize  : Nat
1092 |               lastsize  = plus (lastAt sizes) 1
1093 |               children' = append children (fill 1 (newBranch x (down sh)))
1094 |               sizes'    = append sizes (fill 1 lastsize)
1095 |             in Unbalanced (MkRelaxedChildren {n = plus (S k) 1} {nonEmpty = believe_me ()} {withinBlock = believe_me ()} children' sizes')
1096 |         GT =>
1097 |           let lastsize : Nat
1098 |               lastsize = plus (lastAt sizes) 1
1099 |             in assert_total (Unbalanced (MkRelaxedChildren {n = S k} {nonEmpty = nonEmpty} {withinBlock = withinBlock} (updateAt lastFin (snocTree $ down sh) children) (setAt lastFin lastsize sizes)))
1100 |     snocTree _  (Leaf arr)                                                                         =
1101 |       Leaf (A (plus arr.size 1) (append arr.arr (fill 1 x)))
1102 |
1103 | ||| Concatenates two vectors. O(log(max(n1,n2)))
1104 | |||
1105 | export
1106 | (><) :  RRBVector a
1107 |      -> RRBVector a
1108 |      -> RRBVector a
1109 | Empty                >< v                    = v
1110 | v                    >< Empty                = v
1111 | Root size1 sh1 tree1 >< Root size2 sh2 tree2 =
1112 |   let upmaxshift   = case compare sh1 sh2 of
1113 |                        LT =>
1114 |                          up sh2
1115 |                        EQ =>
1116 |                          up sh1
1117 |                        GT =>
1118 |                          up sh1
1119 |       newarr       = mergeTrees tree1 sh1 tree2 sh2
1120 |       rootchildren : Children a
1121 |       rootchildren = childrenFromArray newarr
1122 |     in normalize (Root (plus size1 size2) upmaxshift (computeSizes upmaxshift rootchildren))
1123 |   where
1124 |     ||| Remove and return the first child of a nonempty tree array.
1125 |     |||
1126 |     ||| Arrays passed here originate from internal tree nodes and are therefore
1127 |     ||| structurally nonempty.
1128 |     |||
1129 |     viewlArr :  Array (Tree a)
1130 |              -> (Tree a, Array (Tree a))
1131 |     viewlArr (A Z _)       =
1132 |       assert_total (idris_crash "Data.RRBVector.(><).viewlArr: empty internal array")
1133 |     viewlArr (A (S n) arr) =
1134 |       let tail : IArray (minus n 0) (Tree a)
1135 |           tail = force (drop 1 arr)
1136 |         in ( at arr FZ
1137 |            , A (minus n 0) tail
1138 |            )
1139 |     ||| Remove and return the final child of a nonempty tree array.
1140 |     |||
1141 |     ||| The final position is represented directly by `lastFin`, avoiding a
1142 |     ||| dynamic conversion of `size - 1`.
1143 |     |||
1144 |     viewrArr :  Array (Tree b)
1145 |              -> (Array (Tree b), Tree b)
1146 |     viewrArr (A Z _)       =
1147 |       assert_total (idris_crash "Data.RRBVector.(><).viewrArr: empty internal array")
1148 |     viewrArr (A (S n) arr) =
1149 |       let 0 initLTE : LTE n (S n)
1150 |           initLTE   = believe_me ()
1151 |           init      : IArray n (Tree b)
1152 |           init      = force (take n arr @{initLTE})
1153 |         in ( A n init
1154 |            , at arr (lastFin {n})
1155 |            )
1156 |     mergeRebalance' :  Shift
1157 |                     -> Array (Tree a)
1158 |                     -> Array (Tree a)
1159 |                     -> Array (Tree a)
1160 |                     -> (Tree a -> Array (Tree a))
1161 |                     -> (Array (Tree a) -> Tree a)
1162 |                     -> Array (Tree a)
1163 |     mergeRebalance' sh left center right extract construct =
1164 |       run1 $ \t =>
1165 |         let nodecounter    # t := ref1 Z t
1166 |             subtreecounter # t := ref1 Z t
1167 |             newnode        # t := ref1 Lin t
1168 |             newsubtree     # t := ref1 Lin t
1169 |             newroot        # t := ref1 Lin t
1170 |             ()             # t := mergeRebalanceSubtree' sh nodecounter subtreecounter newnode newsubtree newroot extract construct (toList left ++ toList center ++ toList right) t
1171 |             newnode'       # t := read1 newnode t
1172 |             ()             # t := casmod1 newsubtree (\y => y :< (construct $ A (SnocSize newnode')
1173 |                                                                                 (snocConcat newnode'))
1174 |                                                      ) t                
1175 |             newsubtree'    # t := read1 newsubtree t
1176 |             ()             # t := casmod1 newroot (\y => y :< (computeSizes sh (childrenFromArray (fromList (cast {to=List (Tree a)} newsubtree'))))
1177 |                                                   ) t
1178 |             newroot'       # t := read1 newroot t
1179 |           in fromList (cast {to=List (Tree a)} newroot') # t
1180 |       where
1181 |         mergeRebalanceSubtreeNodeCounter :  Ref s Nat
1182 |                                          -> Ref s Nat
1183 |                                          -> Ref s (SnocList (Array (Tree a)))
1184 |                                          -> Ref s (SnocList (Tree a))
1185 |                                          -> (Array (Tree a) -> Tree a)
1186 |                                          -> F1' s
1187 |         mergeRebalanceSubtreeNodeCounter nodecounter subtreecounter newnode newsubtree construct t =
1188 |           let newnode' # t := read1 newnode t
1189 |               ()       # t := casmod1 newsubtree (\y => y :< (construct $ A (SnocSize newnode')
1190 |                                                                             (snocConcat newnode'))
1191 |                                                  ) t
1192 |               ()       # t := write1 newnode Lin t
1193 |               ()       # t := write1 nodecounter Z t
1194 |             in casmod1 subtreecounter (\y => y + 1) t
1195 |         mergeRebalanceRootSubtreeCounter :  Shift
1196 |                                          -> Ref s Nat
1197 |                                          -> Ref s (SnocList (Tree a))
1198 |                                          -> Ref s (SnocList (Tree a))
1199 |                                          -> F1' s
1200 |         mergeRebalanceRootSubtreeCounter sh subtreecounter newsubtree newroot t =
1201 |           let newsubtree' # t := read1 newsubtree t
1202 |               ()          # t := casmod1 newroot (\y => y :< (computeSizes sh (childrenFromArray (fromList (cast {to=List (Tree a)} newsubtree'))))
1203 |                                                  ) t
1204 |               ()          # t := write1 newsubtree Lin t
1205 |             in write1 subtreecounter Z t
1206 |         mergeRebalanceSubtree''' :  Shift
1207 |                                  -> Ref s Nat
1208 |                                  -> Ref s Nat
1209 |                                  -> Ref s (SnocList (Array (Tree a)))
1210 |                                  -> Ref s (SnocList (Tree a))
1211 |                                  -> Ref s (SnocList (Tree a))
1212 |                                  -> (Array (Tree a) -> Tree a)
1213 |                                  -> Tree a
1214 |                                  -> F1' s
1215 |         mergeRebalanceSubtree''' sh nodecounter subtreecounter newnode newsubtree newroot construct extractedsubtree t =
1216 |           let nodecounter'    # t := read1 nodecounter t
1217 |               ()              # t := when1 (nodecounter' == blocksize) (mergeRebalanceSubtreeNodeCounter nodecounter subtreecounter newnode newsubtree construct) t
1218 |               subtreecounter' # t := read1 subtreecounter t
1219 |               ()              # t := when1 (subtreecounter' == blocksize) (mergeRebalanceRootSubtreeCounter sh subtreecounter newsubtree newroot) t
1220 |               ()              # t := casmod1 newnode (\y => y :< (fill 1 extractedsubtree)
1221 |                                                      ) t
1222 |             in casmod1 nodecounter (\y => y + 1) t        
1223 |         mergeRebalanceSubtree'' :  Shift
1224 |                                 -> Ref s Nat
1225 |                                 -> Ref s Nat
1226 |                                 -> Ref s (SnocList (Array (Tree a)))
1227 |                                 -> Ref s (SnocList (Tree a))
1228 |                                 -> Ref s (SnocList (Tree a))
1229 |                                 -> (Tree a -> Array (Tree a))
1230 |                                 -> (Array (Tree a) -> Tree a)
1231 |                                 -> Tree a
1232 |                                 -> F1' s
1233 |         mergeRebalanceSubtree'' sh nodecounter subtreecounter newnode newsubtree newroot extract construct subtree t =
1234 |           traverse1_ (mergeRebalanceSubtree''' sh nodecounter subtreecounter newnode newsubtree newroot construct) (extract subtree) t
1235 |         mergeRebalanceSubtree' :  Shift
1236 |                                -> Ref s Nat
1237 |                                -> Ref s Nat
1238 |                                -> Ref s (SnocList (Array (Tree a)))
1239 |                                -> Ref s (SnocList (Tree a))
1240 |                                -> Ref s (SnocList (Tree a))
1241 |                                -> (Tree a -> Array (Tree a))
1242 |                                -> (Array (Tree a) -> Tree a)
1243 |                                -> List (Tree a)
1244 |                                -> F1' s
1245 |         mergeRebalanceSubtree' sh nodecounter subtreecounter newnode newsubtree newroot extract construct leftcenterright t =
1246 |           traverse1_ (mergeRebalanceSubtree'' sh nodecounter subtreecounter newnode newsubtree newroot extract construct) leftcenterright t
1247 |     mergeRebalance'' :  Shift
1248 |                      -> Array (Tree a)
1249 |                      -> Array (Tree a)
1250 |                      -> Array (Tree a)
1251 |                      -> (Tree a -> Array a)
1252 |                      -> (Array a -> Tree a)
1253 |                      -> Array (Tree a)
1254 |     mergeRebalance'' sh left center right extract construct =
1255 |       run1 $ \t =>
1256 |         let nodecounter    # t := ref1 Z t
1257 |             subtreecounter # t := ref1 Z t
1258 |             newnode        # t := ref1 Lin t
1259 |             newsubtree     # t := ref1 Lin t
1260 |             newroot        # t := ref1 Lin t
1261 |             ()             # t := mergeRebalanceSubtree' sh nodecounter subtreecounter newnode newsubtree newroot extract construct (toList left ++ toList center ++ toList right) t
1262 |             newnode'       # t := read1 newnode t
1263 |             ()             # t := casmod1 newsubtree (\y => y :< (construct $ A (SnocSize newnode')
1264 |                                                                                 (snocConcat newnode'))
1265 |                                                      ) t                
1266 |             newsubtree'    # t := read1 newsubtree t
1267 |             ()             # t := casmod1 newroot (\y => y :< (computeSizes sh (childrenFromArray (fromList (cast {to=List (Tree a)} newsubtree'))))
1268 |                                                   ) t
1269 |             newroot'       # t := read1 newroot t
1270 |           in fromList (cast {to=List (Tree a)} newroot') # t
1271 |       where
1272 |         mergeRebalanceSubtreeNodeCounter :  Ref s Nat
1273 |                                          -> Ref s Nat
1274 |                                          -> Ref s (SnocList (Array a))
1275 |                                          -> Ref s (SnocList (Tree a))
1276 |                                          -> (Array a -> Tree a)
1277 |                                          -> F1' s
1278 |         mergeRebalanceSubtreeNodeCounter nodecounter subtreecounter newnode newsubtree construct t =
1279 |           let newnode' # t := read1 newnode t
1280 |               ()       # t := casmod1 newsubtree (\y => y :< (construct $ A (SnocSize newnode')
1281 |                                                                             (snocConcat newnode'))
1282 |                                                  ) t
1283 |               ()       # t := write1 newnode Lin t
1284 |               ()       # t := write1 nodecounter Z t
1285 |             in casmod1 subtreecounter (\y => y + 1) t
1286 |         mergeRebalanceRootSubtreeCounter :  Shift
1287 |                                          -> Ref s Nat
1288 |                                          -> Ref s (SnocList (Tree a))
1289 |                                          -> Ref s (SnocList (Tree a))
1290 |                                          -> F1' s
1291 |         mergeRebalanceRootSubtreeCounter sh subtreecounter newsubtree newroot t =
1292 |           let newsubtree' # t := read1 newsubtree t
1293 |               ()          # t := casmod1 newroot (\y => y :< (computeSizes sh (childrenFromArray (fromList (cast {to=List (Tree a)} newsubtree'))))
1294 |                                                  ) t
1295 |               ()          # t := write1 newsubtree Lin t
1296 |             in write1 subtreecounter Z t
1297 |         mergeRebalanceSubtree''' :  Shift
1298 |                                  -> Ref s Nat
1299 |                                  -> Ref s Nat
1300 |                                  -> Ref s (SnocList (Array a))
1301 |                                  -> Ref s (SnocList (Tree a))
1302 |                                  -> Ref s (SnocList (Tree a))
1303 |                                  -> (Array a -> Tree a)
1304 |                                  -> a
1305 |                                  -> F1' s
1306 |         mergeRebalanceSubtree''' sh nodecounter subtreecounter newnode newsubtree newroot construct extractedsubtree t =
1307 |           let nodecounter'    # t := read1 nodecounter t
1308 |               ()              # t := when1 (nodecounter' == blocksize) (mergeRebalanceSubtreeNodeCounter nodecounter subtreecounter newnode newsubtree construct) t
1309 |               subtreecounter' # t := read1 subtreecounter t
1310 |               ()              # t := when1 (subtreecounter' == blocksize) (mergeRebalanceRootSubtreeCounter sh subtreecounter newsubtree newroot) t
1311 |               ()              # t := casmod1 newnode (\y => y :< (fill 1 extractedsubtree)
1312 |                                                      ) t
1313 |             in casmod1 nodecounter (\y => y + 1) t        
1314 |         mergeRebalanceSubtree'' :  Shift
1315 |                                 -> Ref s Nat
1316 |                                 -> Ref s Nat
1317 |                                 -> Ref s (SnocList (Array a))
1318 |                                 -> Ref s (SnocList (Tree a))
1319 |                                 -> Ref s (SnocList (Tree a))
1320 |                                 -> (Tree a -> Array a)
1321 |                                 -> (Array a -> Tree a)
1322 |                                 -> Tree a
1323 |                                 -> F1' s
1324 |         mergeRebalanceSubtree'' sh nodecounter subtreecounter newnode newsubtree newroot extract construct subtree t =
1325 |           traverse1_ (mergeRebalanceSubtree''' sh nodecounter subtreecounter newnode newsubtree newroot construct) (extract subtree) t
1326 |         mergeRebalanceSubtree' :  Shift
1327 |                                -> Ref s Nat
1328 |                                -> Ref s Nat
1329 |                                -> Ref s (SnocList (Array a))
1330 |                                -> Ref s (SnocList (Tree a))
1331 |                                -> Ref s (SnocList (Tree a))
1332 |                                -> (Tree a -> Array a)
1333 |                                -> (Array a -> Tree a)
1334 |                                -> List (Tree a)
1335 |                                -> F1' s
1336 |         mergeRebalanceSubtree' sh nodecounter subtreecounter newnode newsubtree newroot extract construct leftcenterright t =
1337 |           traverse1_ (mergeRebalanceSubtree'' sh nodecounter subtreecounter newnode newsubtree newroot extract construct) leftcenterright t
1338 |     mergeRebalance :  Shift
1339 |                    -> Array (Tree a)
1340 |                    -> Array (Tree a)
1341 |                    -> Array (Tree a)
1342 |                    -> Array (Tree a)
1343 |     mergeRebalance sh left center right =
1344 |       case compare sh blockshift of
1345 |         LT =>
1346 |           assert_total (mergeRebalance' sh left center right treeToArray (\arr => computeSizes (down sh) (childrenFromArray arr)))
1347 |         EQ =>
1348 |           assert_total (mergeRebalance'' sh left center right (\(Leaf arr) => arr) Leaf)
1349 |         GT =>
1350 |           assert_total (mergeRebalance' sh left center right treeToArray (\arr => computeSizes (down sh) (childrenFromArray arr)))
1351 |     mergeTrees :  Tree a
1352 |                -> Nat
1353 |                -> Tree a
1354 |                -> Nat
1355 |                -> Array (Tree a)
1356 |     mergeTrees tree1@(Leaf arr1) _   tree2@(Leaf arr2) _   =
1357 |       case compare arr1.size blocksize of
1358 |         LT =>
1359 |           let arr' = A (plus arr1.size arr2.size) (append arr1.arr arr2.arr)
1360 |             in case compare arr'.size blocksize of
1361 |                  LT =>
1362 |                    singleton $ Leaf arr'
1363 |                  EQ =>
1364 |                    singleton $ Leaf arr'
1365 |                  GT =>
1366 |                    let (left, right) = (take blocksize arr',drop blocksize arr')
1367 |                        lefttree      = Leaf left
1368 |                        righttree     = Leaf right
1369 |                      in A 2 $ fromPairs 2 lefttree [(1,righttree)]
1370 |         EQ =>
1371 |           A 2 $ fromPairs 2 tree1 [(1,tree2)]
1372 |         GT =>
1373 |           let arr' = A (plus arr1.size arr2.size) (append arr1.arr arr2.arr)
1374 |             in case compare arr'.size blocksize of
1375 |                  LT =>
1376 |                    singleton $ Leaf arr'
1377 |                  EQ =>
1378 |                    singleton $ Leaf arr'
1379 |                  GT =>
1380 |                    let (left, right) = (take blocksize arr',drop blocksize arr')
1381 |                        lefttree      = Leaf left
1382 |                        righttree     = Leaf right
1383 |                      in A 2 $ fromPairs 2 lefttree [(1,righttree)]
1384 |     mergeTrees tree1             sh1 tree2             sh2 =
1385 |       case compare sh1 sh2 of
1386 |         LT =>
1387 |           let right                  = treeToArray tree2
1388 |               (righthead, righttail) = viewlArr right
1389 |               merged                 = assert_total $ mergeTrees tree1 sh1 righthead (down sh2)
1390 |             in mergeRebalance sh2 empty merged righttail
1391 |         GT =>
1392 |           let left                 = treeToArray tree1
1393 |               (leftinit, leftlast) = viewrArr left
1394 |               merged               = assert_total $ mergeTrees leftlast (down sh1) tree2 sh2
1395 |             in mergeRebalance sh1 leftinit merged empty
1396 |         EQ =>
1397 |           let left                   = treeToArray tree1
1398 |               right                  = treeToArray tree2
1399 |               (leftinit, leftlast)   = viewrArr left
1400 |               (righthead, righttail) = viewlArr right
1401 |               merged                 = assert_total $ mergeTrees leftlast (down sh1) righthead (down sh2)
1402 |             in mergeRebalance sh1 leftinit merged righttail
1403 |
1404 | ||| Insert an element at the given index, shifting the rest of the vector over.
1405 | ||| If the index is negative, add the element to the left end of the vector.
1406 | ||| If the index is bigger than or equal to the length of the vector, add the element to the right end of the vector. O(log n)
1407 | |||
1408 | export
1409 | insertAt :  Nat
1410 |          -> a
1411 |          -> RRBVector a
1412 |          -> RRBVector a
1413 | insertAt i x v =
1414 |   let (left, right) = splitAt i v
1415 |     in (left |> x) >< right
1416 |
1417 | ||| Delete the element at the given index.
1418 | ||| If the index is out of range, return the original vector. O(log n)
1419 | |||
1420 | export
1421 | deleteAt :  Nat
1422 |          -> RRBVector a
1423 |          -> RRBVector a
1424 | deleteAt i v =
1425 |   let (left, right) = splitAt (plus i 1) v
1426 |     in take i left >< right
1427 |
1428 | --------------------------------------------------------------------------------
1429 | --          Show Utilities (RRB-Vector)
1430 | --------------------------------------------------------------------------------
1431 |
1432 | ||| Show the full representation of the vector.
1433 | |||
1434 | export
1435 | showRRBVectorRep :  Show a
1436 |                  => Show (Tree a)
1437 |                  => Show (RRBVector a)
1438 |                  => RRBVector a
1439 |                  -> String
1440 | showRRBVectorRep Empty            =
1441 |   ""
1442 | showRRBVectorRep (Root size sh t) =
1443 |   "RRBVector "    ++
1444 |   "{ "            ++
1445 |   "Size = "       ++
1446 |   (show size)     ++
1447 |   ", Shift = "    ++
1448 |   (show sh)       ++
1449 |   ", Tree = "     ++
1450 |   (showTreeRep t) ++
1451 |   "}"
1452 |
1453 | --------------------------------------------------------------------------------
1454 | --          Interfaces (RRBVector)
1455 | --------------------------------------------------------------------------------
1456 |
1457 | export
1458 | Eq a => Eq (RRBVector a) where
1459 |   xs == ys = length xs == length ys && Data.RRBVector.toList xs == Data.RRBVector.toList ys
1460 |
1461 | export
1462 | Ord a => Ord (RRBVector a) where
1463 |   compare xs ys = compare (Data.RRBVector.toList xs) (Data.RRBVector.toList ys)
1464 |
1465 | export
1466 | Functor RRBVector where
1467 |   map f v = map f v
1468 |
1469 | export
1470 | Foldable RRBVector where
1471 |   foldl f z           = Data.RRBVector.foldl f z
1472 |   foldr f z           = Data.RRBVector.foldr f z
1473 |   null                = null
1474 |
1475 | export
1476 | Applicative RRBVector where
1477 |   pure      = singleton
1478 |   fs <*> xs = Data.RRBVector.foldl (\acc, f => acc >< map f xs) empty fs
1479 |
1480 | export
1481 | Semigroup (RRBVector a) where
1482 |   (<+>) = (><)
1483 |
1484 | export
1485 | Semigroup (RRBVector a) => Monoid (RRBVector a) where
1486 |   neutral = empty
1487 |
1488 | export
1489 | Monad RRBVector where
1490 |   xs >>= f = Data.RRBVector.foldl (\acc, x => acc >< f x) empty xs
1491 |