module Data.Order.Algorithm ( -- * Algorithms in general Algorithm, withRawAlgorithm, -- * Specific algorithms defaultAlgorithm, dumb, dietzSleatorAmortizedLog, dietzSleatorAmortizedLogWithSize ) where -- Control import Control.Monad.ST -- Data import Data.Order.Algorithm.Type import Data.Order.Algorithm.Raw import qualified Data.Order.Algorithm.Raw.Default as Default import qualified Data.Order.Algorithm.Raw.Dumb as Dumb import qualified Data.Order.Algorithm.Raw.DietzSleatorAmortizedLog as DietzSleatorAmortizedLog {-FIXME: Implement the following: • an algorithm that uses arbitarily deep log-trees • the file maintenance algorithm by Bender et al. combined with log-trees of fixed height • a function that converts any algorithm into one that shifts elements between two orders upon deletion (for avoiding sparsly populated order structures) Maybe it makes sense to additionally offer the file maintenance algorithm by Bender et al. as an order maintenance algorithm in its own right. -} {-FIXME: For implementing Bender et al., it might be good to store the calibrator tree in an array, level by level from top to bottom. The array must then be created without initializing its elements. Initially the tree would be small; so few array elements would be used. When extending the tree, we would face the problem that initializing all the additionally used elements would take more than O(1) time. We can maybe use the trick by Barak A. Pearlmutter¹ (or a variant of it, specialized for our particular initialization pattern) to get O(1) time. ¹ See his e-mail to me from 5 December 2014. -} {-FIXME: More notes regarding implementing Bender et al.: • We can store the set of all children of a single node of a log-tree in an array of 48 64-bit words. Each word represents one child. Children are stored in the temporal order of their allocation. 48 bits of a word are the label, 3 are the left sibling index, 3 are the right sibling index. The parent pointer (pointer to the array plus index in the array) has to be stored only once per such an array, not for every child. • A block in the file maintenance data structure could encompass 48 or maybe also 64 elements. A 64-bit word could be used to store which of the array cells are taken by an element and which are free. • I think that on the upper two levels of a log tree, we need up to three times as many nodes for storing log-many subtrees, because of overflow nodes. This would mean that with the above approach, we could store up to 48 × 12 × 12 ≈ 7000 elements in a log tree and ca. 7000 × 48 ≈ 350000 actual elements per file maintenance block. The total memory use would be a bit more than 8 × 350000 = 2.8 MB. • The number of actual elements per file maintenance block (350,000) would be a bit more than 2^18. Since our k would be 48, we could have up to 2^48 × 2^18 = 2^66 elements theoretically. So we could reach the maximum of 2^64 elements. -} -- * Algorithms in general -- NOTE: Algorithm is imported from Data.OrderMaintenance.Algorithm.Type. withRawAlgorithm :: Algorithm -> (forall o e . (forall s . RawAlgorithm s o e) -> r) -> r withRawAlgorithm (Algorithm rawAlg) cont = cont rawAlg -- * Specific algorithms defaultAlgorithm :: Algorithm defaultAlgorithm = Algorithm Default.rawAlgorithm dumb :: Algorithm dumb = Algorithm Dumb.rawAlgorithm dietzSleatorAmortizedLog :: Algorithm dietzSleatorAmortizedLog = Algorithm DietzSleatorAmortizedLog.rawAlgorithm dietzSleatorAmortizedLogWithSize :: Int -> Algorithm dietzSleatorAmortizedLogWithSize size = Algorithm (DietzSleatorAmortizedLog.rawAlgorithmWithSize size)