{-# LANGUAGE TypeOperators #-}
-----------------------------------------------------------------------------
-- |
-- Module      : Data.Array.Vector.Strict.Enum
-- Copyright   : (c) [2001..2002] Manuel M T Chakravarty & Gabriele Keller
--		 (c) 2006         Manuel M T Chakravarty & Roman Leshchinskiy
-- License     : see libraries/ndp/LICENSE
-- 
-- Maintainer  : Roman Leshchinskiy <rl@cse.unsw.edu.au>
-- Stability   : internal
-- Portability : portable
--
-- Description ---------------------------------------------------------------
--
--  Enum-related operations on flat unlifted arrays.
--
-- Todo ----------------------------------------------------------------------
--

{-# LANGUAGE CPP #-}

#include "fusion-phases.h"

module Data.Array.Vector.Strict.Enum (
  enumFromToU, enumFromToFracU,
  enumFromThenToU, enumFromStepLenU, enumFromToEachU
) where

import Data.Array.Vector.Stream
import Data.Array.Vector.UArr
import Data.Array.Vector.Prim.Hyperstrict
import Data.Array.Vector.Strict.Stream

-- |/O(n)/. 'enumFromToU' yields an enumerated array, analogous to 'enumFromTo',
-- but only works on instances of Integral.
--

-- FIXME: See comments about enumFromThenToS
enumFromToU :: (UA a, Integral a) => a -> a -> UArr a
{-# INLINE_U enumFromToU #-}
enumFromToU start end = unstreamU (enumFromToS start end)

-- |/O(n)/. Like 'enumFromToU', but works on fractional numbers (still 
-- incrementing by 1 each time).
enumFromToFracU :: (UA a, RealFrac a) => a -> a -> UArr a
{-# INLINE_U enumFromToFracU #-}
enumFromToFracU start end = unstreamU (enumFromToFracS start end)

-- |/O(n)/. 'enumFromThenToU' yields an enumerated array using a specific 
-- step value.
--

-- FIXME: See comments about enumFromThenToS
enumFromThenToU :: Int -> Int -> Int -> UArr Int
{-# INLINE_U enumFromThenToU #-}
enumFromThenToU start next end = unstreamU (enumFromThenToS start next end)

-- |/O(n)/. @'enumFromStepLenU' s d n@ yields an enumerated array of length @n@
-- starting from @s@ with an increment of @d@.
--
enumFromStepLenU :: Int -> Int -> Int -> UArr Int
{-# INLINE_U enumFromStepLenU #-}
enumFromStepLenU s d n = unstreamU (enumFromStepLenS s d n)

-- |/O(n)/. @'enumFromToEachU' n u@ yields an array by taking each strict pair
-- @u@ and treating it as a range to generate successive values over. For
-- example:
--
-- @enumFromToEachU 7 (toU [3 :*: 6, 8 :*: 10])@
-- yields @toU [3,4,5,6,8,9,10]@ 
--
-- /N.B/: This function will allocate @n@ slots for the output array, and will
-- happily overrun its allocated space if the @u@ leads it to do so. The caller
-- is expected to ensure that @n <= (sumU . mapU (\(x :*: y) -> y - x + 1) $ u)@.
--
enumFromToEachU :: Int -> UArr (Int :*: Int) -> UArr Int
{-# INLINE_U enumFromToEachU #-}
enumFromToEachU n = unstreamU . enumFromToEachS n . streamU