module Data.Rhythm.Christoffel
( christoffelWord,
)
where
import Data.Bool (bool)
import Data.List.NonEmpty (NonEmpty (..))
import Data.List.NonEmpty qualified as NE
import Data.Maybe (fromMaybe)
christoffelWord :: Bool -> Integer -> Integer -> Maybe Int -> [Integer]
christoffelWord :: Bool -> Integer -> Integer -> Maybe Int -> [Integer]
christoffelWord Bool
isUpperWord Integer
numerator Integer
denominator Maybe Int
nTerms =
Int -> NonEmpty Integer -> [Integer]
forall a. Int -> NonEmpty a -> [a]
NE.take Int
k (NonEmpty Integer -> [Integer]) -> NonEmpty Integer -> [Integer]
forall a b. (a -> b) -> a -> b
$
NonEmpty Integer -> NonEmpty Integer
forall a. NonEmpty a -> NonEmpty a
NE.cycle (NonEmpty Integer -> NonEmpty Integer)
-> NonEmpty Integer -> NonEmpty Integer
forall a b. (a -> b) -> a -> b
$
Integer -> Integer -> Bool -> Integer
forall a. a -> a -> Bool -> a
bool Integer
0 Integer
1 Bool
isUpperWord Integer -> [Integer] -> NonEmpty Integer
forall a. a -> [a] -> NonEmpty a
:| Int -> Integer -> Integer -> [Integer]
forall {a}. Num a => Int -> Integer -> Integer -> [a]
go Int
1 Integer
numerator Integer
denominator
where
go :: Int -> Integer -> Integer -> [a]
go !Int
i !Integer
a !Integer
b
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
n = []
| Bool
otherwise =
case Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Integer
a Integer
b of
Ordering
GT -> a
1 a -> [a] -> [a]
forall a. a -> [a] -> [a]
: Int -> Integer -> Integer -> [a]
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Integer
a (Integer
b Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
denominator)
Ordering
EQ -> a -> a -> Bool -> a
forall a. a -> a -> Bool -> a
bool a
1 a
0 Bool
isUpperWord a -> [a] -> [a]
forall a. a -> [a] -> [a]
: Int -> Integer -> Integer -> [a]
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Integer
numerator Integer
denominator
Ordering
LT -> a
0 a -> [a] -> [a]
forall a. a -> [a] -> [a]
: Int -> Integer -> Integer -> [a]
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (Integer
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
numerator) Integer
b
n :: Int
n = Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer
numerator Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
denominator)
k :: Int
k = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
n Maybe Int
nTerms