{-# LANGUAGE Rank2Types #-}
module Synthesizer.LLVM.Fold where

import qualified LLVM.Extra.Arithmetic as A
import LLVM.Core (CodeGenFunction)

import Control.Applicative (liftA2, liftA3)

import Prelude hiding (sum)


data T a b = Cons (forall r. b -> a -> CodeGenFunction r b) b

premap :: (forall r. a -> CodeGenFunction r b) -> T b c -> T a c
premap :: forall a b c.
(forall r. a -> CodeGenFunction r b) -> T b c -> T a c
premap forall r. a -> CodeGenFunction r b
f (Cons forall r. c -> b -> CodeGenFunction r c
acc c
b0) = (forall r. c -> a -> CodeGenFunction r c) -> c -> T a c
forall a b. (forall r. b -> a -> CodeGenFunction r b) -> b -> T a b
Cons (\c
b a
a -> c -> b -> CodeGenFunction r c
forall r. c -> b -> CodeGenFunction r c
acc c
b (b -> CodeGenFunction r c)
-> CodeGenFunction r b -> CodeGenFunction r c
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< a -> CodeGenFunction r b
forall r. a -> CodeGenFunction r b
f a
a) c
b0


maxZero :: (A.Real a) => T a a
maxZero :: forall a. Real a => T a a
maxZero = (forall r. a -> a -> CodeGenFunction r a) -> a -> T a a
forall a b. (forall r. b -> a -> CodeGenFunction r b) -> b -> T a b
Cons a -> a -> CodeGenFunction r a
forall r. a -> a -> CodeGenFunction r a
forall a r. Real a => a -> a -> CodeGenFunction r a
A.max a
forall a. Additive a => a
A.zero

maxAbs :: (A.Real a) => T a a
maxAbs :: forall a. Real a => T a a
maxAbs = (forall r. a -> CodeGenFunction r a) -> T a a -> T a a
forall a b c.
(forall r. a -> CodeGenFunction r b) -> T b c -> T a c
premap a -> CodeGenFunction r a
forall r. a -> CodeGenFunction r a
forall a r. Real a => a -> CodeGenFunction r a
A.abs T a a
forall a. Real a => T a a
maxZero

sum :: (A.Additive a) => T a a
sum :: forall a. Additive a => T a a
sum = (forall r. a -> a -> CodeGenFunction r a) -> a -> T a a
forall a b. (forall r. b -> a -> CodeGenFunction r b) -> b -> T a b
Cons a -> a -> CodeGenFunction r a
forall r. a -> a -> CodeGenFunction r a
forall a r. Additive a => a -> a -> CodeGenFunction r a
A.add a
forall a. Additive a => a
A.zero

sumSquare :: (A.PseudoRing a) => T a a
sumSquare :: forall a. PseudoRing a => T a a
sumSquare = (forall r. a -> CodeGenFunction r a) -> T a a -> T a a
forall a b c.
(forall r. a -> CodeGenFunction r b) -> T b c -> T a c
premap a -> CodeGenFunction r a
forall r. a -> CodeGenFunction r a
forall a r. PseudoRing a => a -> CodeGenFunction r a
A.square T a a
forall a. Additive a => T a a
sum


pair :: T a0 b0 -> T a1 b1 -> T (a0,a1) (b0,b1)
pair :: forall a0 b0 a1 b1. T a0 b0 -> T a1 b1 -> T (a0, a1) (b0, b1)
pair (Cons forall r. b0 -> a0 -> CodeGenFunction r b0
acc0 b0
b00) (Cons forall r. b1 -> a1 -> CodeGenFunction r b1
acc1 b1
b10) =
   (forall r. (b0, b1) -> (a0, a1) -> CodeGenFunction r (b0, b1))
-> (b0, b1) -> T (a0, a1) (b0, b1)
forall a b. (forall r. b -> a -> CodeGenFunction r b) -> b -> T a b
Cons (\(b0
a0,b1
a1) (a0
b0,a1
b1) -> (b0 -> b1 -> (b0, b1))
-> CodeGenFunction r b0
-> CodeGenFunction r b1
-> CodeGenFunction r (b0, b1)
forall a b c.
(a -> b -> c)
-> CodeGenFunction r a
-> CodeGenFunction r b
-> CodeGenFunction r c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (,) (b0 -> a0 -> CodeGenFunction r b0
forall r. b0 -> a0 -> CodeGenFunction r b0
acc0 b0
a0 a0
b0) (b1 -> a1 -> CodeGenFunction r b1
forall r. b1 -> a1 -> CodeGenFunction r b1
acc1 b1
a1 a1
b1)) (b0
b00,b1
b10)

triple :: T a0 b0 -> T a1 b1 -> T a2 b2 -> T (a0,a1,a2) (b0,b1,b2)
triple :: forall a0 b0 a1 b1 a2 b2.
T a0 b0 -> T a1 b1 -> T a2 b2 -> T (a0, a1, a2) (b0, b1, b2)
triple (Cons forall r. b0 -> a0 -> CodeGenFunction r b0
acc0 b0
b00) (Cons forall r. b1 -> a1 -> CodeGenFunction r b1
acc1 b1
b10) (Cons forall r. b2 -> a2 -> CodeGenFunction r b2
acc2 b2
b20) =
   (forall r.
 (b0, b1, b2) -> (a0, a1, a2) -> CodeGenFunction r (b0, b1, b2))
-> (b0, b1, b2) -> T (a0, a1, a2) (b0, b1, b2)
forall a b. (forall r. b -> a -> CodeGenFunction r b) -> b -> T a b
Cons
      (\(b0
a0,b1
a1,b2
a2) (a0
b0,a1
b1,a2
b2) ->
         (b0 -> b1 -> b2 -> (b0, b1, b2))
-> CodeGenFunction r b0
-> CodeGenFunction r b1
-> CodeGenFunction r b2
-> CodeGenFunction r (b0, b1, b2)
forall (f :: * -> *) a b c d.
Applicative f =>
(a -> b -> c -> d) -> f a -> f b -> f c -> f d
liftA3 (,,) (b0 -> a0 -> CodeGenFunction r b0
forall r. b0 -> a0 -> CodeGenFunction r b0
acc0 b0
a0 a0
b0) (b1 -> a1 -> CodeGenFunction r b1
forall r. b1 -> a1 -> CodeGenFunction r b1
acc1 b1
a1 a1
b1) (b2 -> a2 -> CodeGenFunction r b2
forall r. b2 -> a2 -> CodeGenFunction r b2
acc2 b2
a2 a2
b2))
      (b0
b00,b1
b10,b2
b20)