{- |
Bit manipulation.

Taken from Haskore.

Bit operations work with numbers on the level of ones and zeros.
These functions should be called something like \"pseudo-bit-operations\".
They do not reach into the ones and zeros,
but they do duplicate the effects using regular math.
Note that these bitops, though convenient,
are no more efficient than the high-level arithmetic that does the same thing.
(This is different than in other languages such as C.)
-}

module Sound.MIDI.Bit where

import Data.Maybe.HT (toMaybe, )
import Data.Tuple.HT (swap, )
import Data.Word  (Word8, )
import qualified Data.List as List
import qualified Data.Bits as Bits

{- |
Shift bitwise to the left and right.
-}

shiftL, shiftR :: Bits.Bits a => Int -> a -> a
shiftL :: Int -> a -> a
shiftL = (a -> Int -> a) -> Int -> a -> a
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> Int -> a
forall a. Bits a => a -> Int -> a
Bits.shiftL
shiftR :: Int -> a -> a
shiftR = (a -> Int -> a) -> Int -> a -> a
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> Int -> a
forall a. Bits a => a -> Int -> a
Bits.shiftR

{- |
The call @toBase n x@ takes a given number x and "chops it up,"
returning its digits in base b.  Its output is in the form of a
big-endian list of ints.  divMod is used because it gives the correct
rounding for negative numbers.  Ex. toBytes 1000 -> toBase 256 1000 ->
(256*3) + 232 -> [ 3 , 232 ]
-}

toBase :: Integral a => a -> a -> [a]
toBase :: a -> a -> [a]
toBase a
b =
   [a] -> [a]
forall a. [a] -> [a]
reverse ([a] -> [a]) -> (a -> [a]) -> a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Maybe (a, a)) -> a -> [a]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
List.unfoldr (\a
n -> Bool -> (a, a) -> Maybe (a, a)
forall a. Bool -> a -> Maybe a
toMaybe (a
na -> a -> Bool
forall a. Ord a => a -> a -> Bool
>a
0) ((a, a) -> (a, a)
forall a b. (a, b) -> (b, a)
swap (a -> a -> (a, a)
forall a. Integral a => a -> a -> (a, a)
divMod a
n a
b)))

toBits, toOctal, toHex, toBytes :: Integral a => a -> [a]
toBytes :: a -> [a]
toBytes = a -> a -> [a]
forall a. Integral a => a -> a -> [a]
toBase a
256
toHex :: a -> [a]
toHex   = a -> a -> [a]
forall a. Integral a => a -> a -> [a]
toBase a
16
toOctal :: a -> [a]
toOctal = a -> a -> [a]
forall a. Integral a => a -> a -> [a]
toBase a
8
toBits :: a -> [a]
toBits  = a -> a -> [a]
forall a. Integral a => a -> a -> [a]
toBase a
2

{- |
Get only n of the least significant bytes of x.  If it takes less than
n digits to express x, then fill the extra digits with zeros.
-}

someBytes :: Integral a => Int -> a -> [Word8]
someBytes :: Int -> a -> [Word8]
someBytes Int
n =
   [Word8] -> [Word8]
forall a. [a] -> [a]
reverse ([Word8] -> [Word8]) -> (a -> [Word8]) -> a -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Word8] -> [Word8]
forall a. Int -> [a] -> [a]
take Int
n ([Word8] -> [Word8]) -> (a -> [Word8]) -> a -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Word8) -> [a] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map a -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([a] -> [Word8]) -> (a -> [a]) -> a -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   (a -> Maybe (a, a)) -> a -> [a]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
List.unfoldr ((a, a) -> Maybe (a, a)
forall a. a -> Maybe a
Just ((a, a) -> Maybe (a, a)) -> (a -> (a, a)) -> a -> Maybe (a, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a, a) -> (a, a)
forall a b. (a, b) -> (b, a)
swap ((a, a) -> (a, a)) -> (a -> (a, a)) -> a -> (a, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a -> (a, a)) -> a -> a -> (a, a)
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> a -> (a, a)
forall a. Integral a => a -> a -> (a, a)
divMod (a
2a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^(Int
8::Int)))

{- |
The fromBase function converts a list of digits in another base into a
single base-10 number.

fromBase b [x,y,z] = x*b^2 + y*b^1 + z*b^0
-}

fromBase :: Integral a => a -> [a] -> a
fromBase :: a -> [a] -> a
fromBase a
base [a]
xs = (a -> a -> a) -> a -> [a] -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\a
a a
x -> a
basea -> a -> a
forall a. Num a => a -> a -> a
*a
aa -> a -> a
forall a. Num a => a -> a -> a
+a
x) a
0 [a]
xs

fromBits, fromOctal, fromHex, fromBytes :: Integral a => [a] -> a
fromBytes :: [a] -> a
fromBytes = a -> [a] -> a
forall a. Integral a => a -> [a] -> a
fromBase a
256
fromHex :: [a] -> a
fromHex   = a -> [a] -> a
forall a. Integral a => a -> [a] -> a
fromBase a
16
fromOctal :: [a] -> a
fromOctal = a -> [a] -> a
forall a. Integral a => a -> [a] -> a
fromBase a
8
fromBits :: [a] -> a
fromBits  = a -> [a] -> a
forall a. Integral a => a -> [a] -> a
fromBase a
2


{- |
Like 'replicate' but for big numbers.
It chops the list into blocks of tractable sizes (e.g. @maxBound::Int@).
-}
replicateBig :: Integer -> Integer -> a -> [a]
replicateBig :: Integer -> Integer -> a -> [a]
replicateBig Integer
base Integer
x a
c =
   let loopSizes :: [Int]
loopSizes = (Integer -> Int) -> [Integer] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer -> Integer -> [Integer]
forall a. Integral a => a -> a -> [a]
toBase Integer
base Integer
x)
       b :: Int
b = Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
base
   in  ([a] -> Int -> [a]) -> [a] -> [Int] -> [a]
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\[a]
cs Int
n -> [[a]] -> [a]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (Int -> [a] -> [[a]]
forall a. Int -> a -> [a]
replicate Int
b [a]
cs) [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ Int -> a -> [a]
forall a. Int -> a -> [a]
replicate Int
n a
c) [] [Int]
loopSizes



{- |
@trunc b n@ takes the b least significant bits of n.
-}

trunc :: Integral a => Int -> a -> a
trunc :: Int -> a -> a
trunc Int
b a
n = a
n a -> a -> a
forall a. Integral a => a -> a -> a
`mod` (a
2a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^Int
b)

{- |
@splitAt b n@ splits a number into a tuple: (before bit b, after bit b).
-}

splitAt :: Integral a => Int -> a -> (a, a)
splitAt :: Int -> a -> (a, a)
splitAt Int
b a
n = a
n a -> a -> (a, a)
forall a. Integral a => a -> a -> (a, a)
`divMod` (a
2a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^Int
b)