-- |
-- Module      : Data.Rhythm.BDF
-- Copyright   : (c) Eric Bailey, 2025
--
-- License     : MIT
-- Maintainer  : eric@ericb.me
-- Stability   : experimental
-- Portability : POSIX
--
-- Fold sequences.
module Data.Rhythm.FoldSequences
  ( foldSequence,
  )
where

import Data.Bits (countTrailingZeros, shiftL, (.&.))
import Data.Bool (bool)

-- | Generate fold sequences from given number of terms, number of bits, and
-- function number \(\{0,\dotsc,2^m-1\}\).
--
-- >>> foldSequence 7 4 2
-- [0,1,1,0,0,0,1]
foldSequence :: Int -> Int -> Int -> [Int]
foldSequence :: Int -> Int -> Int -> [Int]
foldSequence Int
n Int
m Int
f =
  [ Int -> Int -> Bool -> Int
forall a. a -> a -> Bool -> a
bool Int
x (Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
x) ((Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
b Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1)
    | Int
i <- [Int
1 .. Int
n],
      let j :: Int
j = Int
i Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. (-Int
i),
      let (Int
a, Int
b) = (Int -> Int
forall b. FiniteBits b => b -> Int
countTrailingZeros Int
j Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
m, Int
i Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
j)),
      let x :: Int
x = Bool -> Int
forall a. Enum a => a -> Int
fromEnum (Int
0 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== (Int
g Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. (Int
1 Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftL` Int
a)))
  ]
  where
    g :: Int
g = Int
pow2m Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Int
f Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
pow2m) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
    pow2m :: Int
pow2m = Int
2 Int -> Int -> Int
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
m