{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
module Language.Drasil.Expr.Class (
  ExprC(..),
  frac, recip_,
  square, half,
  oneHalf, oneThird,
  apply1, apply2,
  m2x2, vec2D, dgnl2x2, rowVec, columnVec
) where

import Prelude hiding (sqrt, log, sin, cos, tan, exp)

import Control.Lens ((^.))

import Language.Drasil.Symbol
import Language.Drasil.Expr.Lang
import Language.Drasil.Literal.Lang
import Language.Drasil.Space (DomainDesc(..), RTopology(..), RealInterval)
import qualified Language.Drasil.ModelExpr.Lang as M
import qualified Language.Drasil.CodeExpr.Lang as C
import Language.Drasil.Literal.Class (LiteralC(..))
import Language.Drasil.UID (HasUID(..))

import Utils.Drasil (toColumn)

-- | Smart constructor for fractions.
frac :: (ExprC r, LiteralC r) => Integer -> Integer -> r
frac :: forall r. (ExprC r, LiteralC r) => Integer -> Integer -> r
frac Integer
n Integer
d = forall r. LiteralC r => Integer -> r
exactDbl Integer
n forall r. ExprC r => r -> r -> r
$/ forall r. LiteralC r => Integer -> r
exactDbl Integer
d

-- | Smart constructor for rational expressions (only in 1/x form).
recip_ :: (ExprC r, LiteralC r) => r -> r
recip_ :: forall r. (ExprC r, LiteralC r) => r -> r
recip_ r
denom = forall r. LiteralC r => Integer -> r
exactDbl Integer
1 forall r. ExprC r => r -> r -> r
$/ r
denom

-- | Smart constructor to square a function.
square :: (ExprC r, LiteralC r) => r -> r
square :: forall r. (ExprC r, LiteralC r) => r -> r
square r
x = r
x forall r. ExprC r => r -> r -> r
$^ forall r. LiteralC r => Integer -> r
exactDbl Integer
2

-- | Smart constructor to half a function exactly.
half :: (ExprC r, LiteralC r) => r -> r
half :: forall r. (ExprC r, LiteralC r) => r -> r
half r
x = r
x forall r. ExprC r => r -> r -> r
$/ forall r. LiteralC r => Integer -> r
exactDbl Integer
2

-- | 1/2, as an expression.
oneHalf :: (ExprC r, LiteralC r) => r
oneHalf :: forall r. (ExprC r, LiteralC r) => r
oneHalf = forall r. (ExprC r, LiteralC r) => Integer -> Integer -> r
frac Integer
1 Integer
2

-- | 1/3rd, as an expression.
oneThird :: (ExprC r, LiteralC r) => r
oneThird :: forall r. (ExprC r, LiteralC r) => r
oneThird = forall r. (ExprC r, LiteralC r) => Integer -> Integer -> r
frac Integer
1 Integer
3

-- | Similar to 'apply', but converts second argument into 'Symbol's.
apply1 :: (ExprC r, HasUID f, HasSymbol f, HasUID a, HasSymbol a) => f -> a -> r
apply1 :: forall r f a.
(ExprC r, HasUID f, HasSymbol f, HasUID a, HasSymbol a) =>
f -> a -> r
apply1 f
f a
a = forall r f. (ExprC r, HasUID f, HasSymbol f) => f -> [r] -> r
apply f
f [forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy a
a]

-- | Similar to 'apply', but the applied function takes two parameters (which are both 'Symbol's).
apply2 :: (ExprC r, HasUID f, HasSymbol f, HasUID a, HasSymbol a, HasUID b, HasSymbol b) 
    => f -> a -> b -> r
apply2 :: forall r f a b.
(ExprC r, HasUID f, HasSymbol f, HasUID a, HasSymbol a, HasUID b,
 HasSymbol b) =>
f -> a -> b -> r
apply2 f
f a
a b
b = forall r f. (ExprC r, HasUID f, HasSymbol f) => f -> [r] -> r
apply f
f [forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy a
a, forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy b
b]

-- | Create a two-by-two matrix from four given values. For example:
--
-- >>> m2x2 1 2 3 4
-- [ [1,2],
--   [3,4] ]
m2x2 :: ExprC r => r -> r -> r -> r -> r
m2x2 :: forall r. ExprC r => r -> r -> r -> r -> r
m2x2 r
a r
b r
c r
d = forall r. ExprC r => [[r]] -> r
matrix [[r
a,r
b],[r
c,r
d]]

-- | Create a 2D vector (a matrix with two rows, one column). First argument is placed above the second.
vec2D :: ExprC r => r -> r -> r
vec2D :: forall r. ExprC r => r -> r -> r
vec2D r
a r
b = forall r. ExprC r => [[r]] -> r
matrix [[r
a],[r
b]]

-- | Creates a diagonal two-by-two matrix. For example:
--
-- >>> dgnl2x2 1 2
-- [ [1, 0],
--   [0, 2] ]
dgnl2x2 :: (ExprC r, LiteralC r) => r -> r -> r
dgnl2x2 :: forall r. (ExprC r, LiteralC r) => r -> r -> r
dgnl2x2 r
a = forall r. ExprC r => r -> r -> r -> r -> r
m2x2 r
a (forall r. LiteralC r => Integer -> r
int Integer
0) (forall r. LiteralC r => Integer -> r
int Integer
0)

-- | Create a row vector
rowVec :: ExprC r => [r] -> r
rowVec :: forall r. ExprC r => [r] -> r
rowVec [r]
a = forall r. ExprC r => [[r]] -> r
matrix [[r]
a]

-- | Create a column vector
columnVec :: ExprC r => [r] -> r
columnVec :: forall r. ExprC r => [r] -> r
columnVec [r]
a = forall r. ExprC r => [[r]] -> r
matrix forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [[a]]
toColumn [r]
a

class ExprC r where
  infixr 8 $^
  infixl 7 $/
  infixr 4 $=
  infixr 9 $&&
  infixr 9 $||
  
  lit :: Literal -> r

  -- * Binary Operators
  
  ($=), ($!=) :: r -> r -> r
  
  -- | Smart constructor for ordering two equations.
  ($<), ($>), ($<=), ($>=) :: r -> r -> r
  
  -- | Smart constructor for the dot product of two equations.
  ($.) :: r -> r -> r
  
  -- | Add two expressions (Integers).
  addI :: r -> r -> r
  
  -- | Add two expressions (Real numbers).
  addRe :: r -> r -> r
  
  -- | Multiply two expressions (Integers).
  mulI :: r -> r -> r
  
  -- | Multiply two expressions (Real numbers).
  mulRe :: r -> r -> r
  
  ($-), ($/), ($^) :: r -> r -> r
  
  ($=>), ($<=>) :: r -> r -> r
  
  ($&&), ($||) :: r -> r -> r
  
  -- | Smart constructor for taking the absolute value of an expression.
  abs_ :: r -> r
  
  -- | Smart constructor for negating an expression.
  neg :: r -> r 
  
  -- | Smart constructor to take the log of an expression.
  log :: r -> r
  
  -- | Smart constructor to take the ln of an expression.
  ln :: r -> r
  
  -- | Smart constructor to take the square root of an expression.
  sqrt :: r -> r
  
  -- | Smart constructor to apply sin to an expression.
  sin :: r -> r
  
  -- | Smart constructor to apply cos to an expression.
  cos :: r -> r 
  
  -- | Smart constructor to apply tan to an expression.
  tan :: r -> r
  
  -- | Smart constructor to apply sec to an expression.
  sec :: r -> r 
  
  -- | Smart constructor to apply csc to an expression.
  csc :: r -> r
  
  -- | Smart constructor to apply cot to an expression.
  cot :: r -> r 
  
  -- | Smart constructor to apply arcsin to an expression.
  arcsin :: r -> r 
  
  -- | Smart constructor to apply arccos to an expression.
  arccos :: r -> r 
  
  -- | Smart constructor to apply arctan to an expression.
  arctan :: r -> r 
  
  -- | Smart constructor for the exponential (base e) function.
  exp :: r -> r
  
  -- | Smart constructor for calculating the dimension of a vector.
  dim :: r -> r
  
  -- | Smart constructor for calculating the normal form of a vector.
  norm :: r -> r
  
  -- | Smart constructor for negating vectors.
  negVec :: r -> r
  
  -- | Smart constructor for applying logical negation to an expression.
  not_ :: r -> r
  
  -- | Smart constructor for indexing.
  idx :: r -> r -> r
  
  -- | Smart constructor for the summation, product, and integral functions over an interval.
  defint, defsum, defprod :: Symbol -> r -> r -> r -> r
  
  -- | Smart constructor for 'real interval' membership.
  realInterval :: HasUID c => c -> RealInterval r r -> r
  
  -- | Euclidean function : takes a vector and returns the sqrt of the sum-of-squares.
  euclidean :: [r] -> r
  
  -- | Smart constructor to cross product two expressions.
  cross :: r -> r -> r
  
  -- | Smart constructor for vector scaling
  vScale :: r -> r -> r

  -- | Vector Addition
  vAdd :: r -> r -> r

  -- | Vector Subtraction
  vSub :: r -> r -> r

  -- | Smart constructor for case statements with a complete set of cases.
  completeCase :: [(r, r)] -> r
  
  -- | Smart constructor for case statements with an incomplete set of cases.
  incompleteCase :: [(r, r)] -> r
  
  -- | Create a matrix.
  matrix :: [[r]] -> r

  -- | Applies a given function with a list of parameters.
  apply :: (HasUID f, HasSymbol f) => f -> [r] -> r
   
  -- Note how |sy| 'enforces' having a symbol
  -- | Create an 'Expr' from a 'Symbol'ic Chunk.
  sy :: (HasUID c, HasSymbol c) => c -> r

instance ExprC Expr where
  lit :: Literal -> Expr
lit = Literal -> Expr
Lit

  -- | Smart constructor for equating two expressions.
  $= :: Expr -> Expr -> Expr
($=)  = EqBinOp -> Expr -> Expr -> Expr
EqBinaryOp EqBinOp
Eq
  -- | Smart constructor for showing that two expressions are not equal.
  $!= :: Expr -> Expr -> Expr
($!=) = EqBinOp -> Expr -> Expr -> Expr
EqBinaryOp EqBinOp
NEq
  
  -- | Smart constructor for ordering two equations.
  -- | Less than.
  $< :: Expr -> Expr -> Expr
($<)  = OrdBinOp -> Expr -> Expr -> Expr
OrdBinaryOp OrdBinOp
Lt
  -- | Greater than.
  $> :: Expr -> Expr -> Expr
($>)  = OrdBinOp -> Expr -> Expr -> Expr
OrdBinaryOp OrdBinOp
Gt
  -- | Less than or equal to.
  $<= :: Expr -> Expr -> Expr
($<=) = OrdBinOp -> Expr -> Expr -> Expr
OrdBinaryOp OrdBinOp
LEq
  -- | Greater than or equal to.
  $>= :: Expr -> Expr -> Expr
($>=) = OrdBinOp -> Expr -> Expr -> Expr
OrdBinaryOp OrdBinOp
GEq
  
  -- | Smart constructor for the dot product of two equations.
  $. :: Expr -> Expr -> Expr
($.) = VVNBinOp -> Expr -> Expr -> Expr
VVNBinaryOp VVNBinOp
Dot
  
  -- | Add two expressions (Integers).
  addI :: Expr -> Expr -> Expr
addI Expr
l (Lit (Int Integer
0)) = Expr
l
  addI (Lit (Int Integer
0)) Expr
r = Expr
r
  addI (AssocA AssocArithOper
AddI [Expr]
l) (AssocA AssocArithOper
AddI [Expr]
r) = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
AddI ([Expr]
l forall a. [a] -> [a] -> [a]
++ [Expr]
r)
  addI (AssocA AssocArithOper
AddI [Expr]
l) Expr
r = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
AddI ([Expr]
l forall a. [a] -> [a] -> [a]
++ [Expr
r])
  addI Expr
l (AssocA AssocArithOper
AddI [Expr]
r) = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
AddI (Expr
l forall a. a -> [a] -> [a]
: [Expr]
r)
  addI Expr
l Expr
r = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
AddI [Expr
l, Expr
r]
  
  -- | Add two expressions (Real numbers).
  addRe :: Expr -> Expr -> Expr
addRe Expr
l (Lit (Dbl Double
0))= Expr
l
  addRe (Lit(Dbl Double
0)) Expr
r      = Expr
r
  addRe Expr
l (Lit (ExactDbl Integer
0)) = Expr
l
  addRe (Lit (ExactDbl Integer
0)) Expr
r = Expr
r
  addRe (AssocA AssocArithOper
AddRe [Expr]
l) (AssocA AssocArithOper
AddRe [Expr]
r) = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
AddRe ([Expr]
l forall a. [a] -> [a] -> [a]
++ [Expr]
r)
  addRe (AssocA AssocArithOper
AddRe [Expr]
l) Expr
r = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
AddRe ([Expr]
l forall a. [a] -> [a] -> [a]
++ [Expr
r])
  addRe Expr
l (AssocA AssocArithOper
AddRe [Expr]
r) = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
AddRe (Expr
l forall a. a -> [a] -> [a]
: [Expr]
r)
  addRe Expr
l Expr
r = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
AddRe [Expr
l, Expr
r]
  
  -- | Multiply two expressions (Integers).
  mulI :: Expr -> Expr -> Expr
mulI Expr
l (Lit (Int Integer
1)) = Expr
l
  mulI (Lit (Int Integer
1)) Expr
r = Expr
r
  mulI (AssocA AssocArithOper
MulI [Expr]
l) (AssocA AssocArithOper
MulI [Expr]
r) = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
MulI ([Expr]
l forall a. [a] -> [a] -> [a]
++ [Expr]
r)
  mulI (AssocA AssocArithOper
MulI [Expr]
l) Expr
r = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
MulI ([Expr]
l forall a. [a] -> [a] -> [a]
++ [Expr
r])
  mulI Expr
l (AssocA AssocArithOper
MulI [Expr]
r) = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
MulI (Expr
l forall a. a -> [a] -> [a]
: [Expr]
r)
  mulI Expr
l Expr
r = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
MulI [Expr
l, Expr
r]
  
  -- | Multiply two expressions (Real numbers).
  mulRe :: Expr -> Expr -> Expr
mulRe Expr
l (Lit (Dbl Double
1))      = Expr
l
  mulRe (Lit (Dbl Double
1)) Expr
r      = Expr
r
  mulRe Expr
l (Lit (ExactDbl Integer
1)) = Expr
l
  mulRe (Lit (ExactDbl Integer
1)) Expr
r = Expr
r
  mulRe (AssocA AssocArithOper
MulRe [Expr]
l) (AssocA AssocArithOper
MulRe [Expr]
r) = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
MulRe ([Expr]
l forall a. [a] -> [a] -> [a]
++ [Expr]
r)
  mulRe (AssocA AssocArithOper
MulRe [Expr]
l) Expr
r = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
MulRe ([Expr]
l forall a. [a] -> [a] -> [a]
++ [Expr
r])
  mulRe Expr
l (AssocA AssocArithOper
MulRe [Expr]
r) = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
MulRe (Expr
l forall a. a -> [a] -> [a]
: [Expr]
r)
  mulRe Expr
l Expr
r = AssocArithOper -> [Expr] -> Expr
AssocA AssocArithOper
MulRe [Expr
l, Expr
r]
  
  -- | Smart constructor for subtracting two expressions.
  $- :: Expr -> Expr -> Expr
($-) = ArithBinOp -> Expr -> Expr -> Expr
ArithBinaryOp ArithBinOp
Subt
  -- | Smart constructor for dividing two expressions.
  $/ :: Expr -> Expr -> Expr
($/) = ArithBinOp -> Expr -> Expr -> Expr
ArithBinaryOp ArithBinOp
Frac
  -- | Smart constructor for rasing the first expression to the power of the second.
  $^ :: Expr -> Expr -> Expr
($^) = ArithBinOp -> Expr -> Expr -> Expr
ArithBinaryOp ArithBinOp
Pow
  
  -- | Smart constructor to show that one expression implies the other (conditional operator).
  $=> :: Expr -> Expr -> Expr
($=>)  = BoolBinOp -> Expr -> Expr -> Expr
BoolBinaryOp BoolBinOp
Impl
  -- | Smart constructor to show that an expression exists if and only if another expression exists (biconditional operator).
  $<=> :: Expr -> Expr -> Expr
($<=>) = BoolBinOp -> Expr -> Expr -> Expr
BoolBinaryOp BoolBinOp
Iff
  
  -- | Smart constructor for the boolean /and/ operator.
  Expr
a $&& :: Expr -> Expr -> Expr
$&& Expr
b = AssocBoolOper -> [Expr] -> Expr
AssocB AssocBoolOper
And [Expr
a, Expr
b]
  -- | Smart constructor for the boolean /or/ operator.
  Expr
a $|| :: Expr -> Expr -> Expr
$|| Expr
b = AssocBoolOper -> [Expr] -> Expr
AssocB AssocBoolOper
Or  [Expr
a, Expr
b]
  
  -- | Smart constructor for taking the absolute value of an expression.
  abs_ :: Expr -> Expr
abs_ = UFunc -> Expr -> Expr
UnaryOp UFunc
Abs
  
  -- | Smart constructor for negating an expression.
  neg :: Expr -> Expr
neg = UFunc -> Expr -> Expr
UnaryOp UFunc
Neg
  
  -- | Smart constructor to take the log of an expression.
  log :: Expr -> Expr
log = UFunc -> Expr -> Expr
UnaryOp UFunc
Log
  
  -- | Smart constructor to take the ln of an expression.
  ln :: Expr -> Expr
ln = UFunc -> Expr -> Expr
UnaryOp UFunc
Ln
  
  -- | Smart constructor to take the square root of an expression.
  sqrt :: Expr -> Expr
sqrt = UFunc -> Expr -> Expr
UnaryOp UFunc
Sqrt
  
  -- | Smart constructor to apply sin to an expression.
  sin :: Expr -> Expr
sin = UFunc -> Expr -> Expr
UnaryOp UFunc
Sin
  
  -- | Smart constructor to apply cos to an expression.
  cos :: Expr -> Expr
cos = UFunc -> Expr -> Expr
UnaryOp UFunc
Cos
  
  -- | Smart constructor to apply tan to an expression.
  tan :: Expr -> Expr
tan = UFunc -> Expr -> Expr
UnaryOp UFunc
Tan
  
  -- | Smart constructor to apply sec to an expression.
  sec :: Expr -> Expr
sec = UFunc -> Expr -> Expr
UnaryOp UFunc
Sec
  
  -- | Smart constructor to apply csc to an expression.
  csc :: Expr -> Expr
csc = UFunc -> Expr -> Expr
UnaryOp UFunc
Csc
  
  -- | Smart constructor to apply cot to an expression.
  cot :: Expr -> Expr
cot = UFunc -> Expr -> Expr
UnaryOp UFunc
Cot
  
  -- | Smart constructor to apply arcsin to an expression.
  arcsin :: Expr -> Expr
arcsin = UFunc -> Expr -> Expr
UnaryOp UFunc
Arcsin
  
  -- | Smart constructor to apply arccos to an expression.
  arccos :: Expr -> Expr
arccos = UFunc -> Expr -> Expr
UnaryOp UFunc
Arccos
  
  -- | Smart constructor to apply arctan to an expression.
  arctan :: Expr -> Expr
arctan = UFunc -> Expr -> Expr
UnaryOp UFunc
Arctan
  
  -- | Smart constructor for the exponential (base e) function.
  exp :: Expr -> Expr
exp = UFunc -> Expr -> Expr
UnaryOp UFunc
Exp
  
  -- | Smart constructor for calculating the dimension of a vector.
  dim :: Expr -> Expr
dim = UFuncVN -> Expr -> Expr
UnaryOpVN UFuncVN
Dim
  
  -- | Smart constructor for calculating the normal form of a vector.
  norm :: Expr -> Expr
norm = UFuncVN -> Expr -> Expr
UnaryOpVN UFuncVN
Norm
  
  -- | Smart constructor for negating vectors.
  negVec :: Expr -> Expr
negVec = UFuncVV -> Expr -> Expr
UnaryOpVV UFuncVV
NegV
  -- | And more general scaling
  vScale :: Expr -> Expr -> Expr
vScale = NVVBinOp -> Expr -> Expr -> Expr
NVVBinaryOp NVVBinOp
Scale
  
  -- | Smart constructor for applying logical negation to an expression.
  not_ :: Expr -> Expr
not_ = UFuncB -> Expr -> Expr
UnaryOpB UFuncB
Not
  
  -- | Smart constructor for indexing.
  idx :: Expr -> Expr -> Expr
idx = LABinOp -> Expr -> Expr -> Expr
LABinaryOp LABinOp
Index
  
  -- | Integrate over some expression with bounds (∫).
  defint :: Symbol -> Expr -> Expr -> Expr -> Expr
defint Symbol
v Expr
low Expr
high = AssocArithOper -> DiscreteDomainDesc Expr Expr -> Expr -> Expr
Operator AssocArithOper
AddRe (forall a b.
Symbol -> RTopology -> a -> b -> DomainDesc 'Discrete a b
BoundedDD Symbol
v RTopology
Continuous Expr
low Expr
high)
  
  -- | Sum over some expression with bounds (∑).
  defsum :: Symbol -> Expr -> Expr -> Expr -> Expr
defsum Symbol
v Expr
low Expr
high = AssocArithOper -> DiscreteDomainDesc Expr Expr -> Expr -> Expr
Operator AssocArithOper
AddRe (forall a b.
Symbol -> RTopology -> a -> b -> DomainDesc 'Discrete a b
BoundedDD Symbol
v RTopology
Discrete Expr
low Expr
high)
  
  -- | Product over some expression with bounds (∏).
  defprod :: Symbol -> Expr -> Expr -> Expr -> Expr
defprod Symbol
v Expr
low Expr
high = AssocArithOper -> DiscreteDomainDesc Expr Expr -> Expr -> Expr
Operator AssocArithOper
MulRe (forall a b.
Symbol -> RTopology -> a -> b -> DomainDesc 'Discrete a b
BoundedDD Symbol
v RTopology
Discrete Expr
low Expr
high)
  
  -- | Smart constructor for 'real interval' membership.
  realInterval :: forall c. HasUID c => c -> RealInterval Expr Expr -> Expr
realInterval c
c = UID -> RealInterval Expr Expr -> Expr
RealI (c
c forall s a. s -> Getting a s a -> a
^. forall c. HasUID c => Lens' c UID
uid)
  
  -- TODO: Move euclidean to smart constructor
  -- | Euclidean function : takes a vector and returns the sqrt of the sum-of-squares.
  euclidean :: [Expr] -> Expr
euclidean = forall r. ExprC r => r -> r
sqrt forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 forall r. ExprC r => r -> r -> r
addRe forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall r. (ExprC r, LiteralC r) => r -> r
square
  
  -- | Smart constructor to cross product two expressions.
  cross :: Expr -> Expr -> Expr
cross = VVVBinOp -> Expr -> Expr -> Expr
VVVBinaryOp VVVBinOp
Cross
  -- | Adding vectors
  vAdd :: Expr -> Expr -> Expr
vAdd  = VVVBinOp -> Expr -> Expr -> Expr
VVVBinaryOp VVVBinOp
VAdd
  -- | Subtracting vectors
  vSub :: Expr -> Expr -> Expr
vSub  = VVVBinOp -> Expr -> Expr -> Expr
VVVBinaryOp VVVBinOp
VSub
  
  -- | Smart constructor for case statements with a complete set of cases.
  completeCase :: [(Expr, Expr)] -> Expr
completeCase = Completeness -> [(Expr, Expr)] -> Expr
Case Completeness
Complete
  
  -- | Smart constructor for case statements with an incomplete set of cases.
  incompleteCase :: [(Expr, Expr)] -> Expr
incompleteCase = Completeness -> [(Expr, Expr)] -> Expr
Case Completeness
Incomplete
  
  matrix :: [[Expr]] -> Expr
matrix = [[Expr]] -> Expr
Matrix

  -- | Applies a given function with a list of parameters.
  apply :: forall f. (HasUID f, HasSymbol f) => f -> [Expr] -> Expr
apply f
f [] = forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy f
f
  apply f
f [Expr]
ps = UID -> [Expr] -> Expr
FCall (f
f forall s a. s -> Getting a s a -> a
^. forall c. HasUID c => Lens' c UID
uid) [Expr]
ps
  
  -- | Create an 'Expr' from a 'Symbol'ic Chunk.
  sy :: forall c. (HasUID c, HasSymbol c) => c -> Expr
sy c
x = UID -> Expr
C (c
x forall s a. s -> Getting a s a -> a
^. forall c. HasUID c => Lens' c UID
uid)
  
instance ExprC M.ModelExpr where
  lit :: Literal -> ModelExpr
lit = Literal -> ModelExpr
M.Lit

  -- | Smart constructor for equating two expressions.
  $= :: ModelExpr -> ModelExpr -> ModelExpr
($=)  = EqBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.EqBinaryOp EqBinOp
M.Eq
  -- | Smart constructor for showing that two expressions are not equal.
  $!= :: ModelExpr -> ModelExpr -> ModelExpr
($!=) = EqBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.EqBinaryOp EqBinOp
M.NEq

  -- | Smart constructor for ordering two equations.
  -- | Less than.
  $< :: ModelExpr -> ModelExpr -> ModelExpr
($<)  = OrdBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.OrdBinaryOp OrdBinOp
M.Lt
  -- | Greater than.
  $> :: ModelExpr -> ModelExpr -> ModelExpr
($>)  = OrdBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.OrdBinaryOp OrdBinOp
M.Gt
  -- | Less than or equal to.
  $<= :: ModelExpr -> ModelExpr -> ModelExpr
($<=) = OrdBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.OrdBinaryOp OrdBinOp
M.LEq
  -- | Greater than or equal to.
  $>= :: ModelExpr -> ModelExpr -> ModelExpr
($>=) = OrdBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.OrdBinaryOp OrdBinOp
M.GEq

  -- | Smart constructor for the dot product of two equations.
  $. :: ModelExpr -> ModelExpr -> ModelExpr
($.) = VVNBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.VVNBinaryOp VVNBinOp
M.Dot

  -- | Add two expressions (Integers).
  addI :: ModelExpr -> ModelExpr -> ModelExpr
addI ModelExpr
l (M.Lit (Int Integer
0)) = ModelExpr
l
  addI (M.Lit (Int Integer
0)) ModelExpr
r = ModelExpr
r
  addI (M.AssocA AssocArithOper
M.AddI [ModelExpr]
l) (M.AssocA AssocArithOper
M.AddI [ModelExpr]
r) = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.AddI ([ModelExpr]
l forall a. [a] -> [a] -> [a]
++ [ModelExpr]
r)
  addI (M.AssocA AssocArithOper
M.AddI [ModelExpr]
l) ModelExpr
r = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.AddI ([ModelExpr]
l forall a. [a] -> [a] -> [a]
++ [ModelExpr
r])
  addI ModelExpr
l (M.AssocA AssocArithOper
M.AddI [ModelExpr]
r) = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.AddI (ModelExpr
l forall a. a -> [a] -> [a]
: [ModelExpr]
r)
  addI ModelExpr
l ModelExpr
r = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.AddI [ModelExpr
l, ModelExpr
r]

  -- | Add two expressions (Real numbers).
  addRe :: ModelExpr -> ModelExpr -> ModelExpr
addRe ModelExpr
l (M.Lit (Dbl Double
0))      = ModelExpr
l
  addRe (M.Lit (Dbl Double
0)) ModelExpr
r      = ModelExpr
r
  addRe ModelExpr
l (M.Lit (ExactDbl Integer
0)) = ModelExpr
l
  addRe (M.Lit (ExactDbl Integer
0)) ModelExpr
r = ModelExpr
r
  addRe (M.AssocA AssocArithOper
M.AddRe [ModelExpr]
l) (M.AssocA AssocArithOper
M.AddRe [ModelExpr]
r) = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.AddRe ([ModelExpr]
l forall a. [a] -> [a] -> [a]
++ [ModelExpr]
r)
  addRe (M.AssocA AssocArithOper
M.AddRe [ModelExpr]
l) ModelExpr
r = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.AddRe ([ModelExpr]
l forall a. [a] -> [a] -> [a]
++ [ModelExpr
r])
  addRe ModelExpr
l (M.AssocA AssocArithOper
M.AddRe [ModelExpr]
r) = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.AddRe (ModelExpr
l forall a. a -> [a] -> [a]
: [ModelExpr]
r)
  addRe ModelExpr
l ModelExpr
r = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.AddRe [ModelExpr
l, ModelExpr
r]

  -- | Multiply two expressions (Integers).
  mulI :: ModelExpr -> ModelExpr -> ModelExpr
mulI ModelExpr
l (M.Lit (Int Integer
1)) = ModelExpr
l
  mulI (M.Lit (Int Integer
1)) ModelExpr
r = ModelExpr
r
  mulI (M.AssocA AssocArithOper
M.MulI [ModelExpr]
l) (M.AssocA AssocArithOper
M.MulI [ModelExpr]
r) = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.MulI ([ModelExpr]
l forall a. [a] -> [a] -> [a]
++ [ModelExpr]
r)
  mulI (M.AssocA AssocArithOper
M.MulI [ModelExpr]
l) ModelExpr
r = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.MulI ([ModelExpr]
l forall a. [a] -> [a] -> [a]
++ [ModelExpr
r])
  mulI ModelExpr
l (M.AssocA AssocArithOper
M.MulI [ModelExpr]
r) = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.MulI (ModelExpr
l forall a. a -> [a] -> [a]
: [ModelExpr]
r)
  mulI ModelExpr
l ModelExpr
r = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.MulI [ModelExpr
l, ModelExpr
r]

  -- | Multiply two expressions (Real numbers).
  mulRe :: ModelExpr -> ModelExpr -> ModelExpr
mulRe ModelExpr
l (M.Lit (Dbl Double
1))      = ModelExpr
l
  mulRe (M.Lit (Dbl Double
1)) ModelExpr
r      = ModelExpr
r
  mulRe ModelExpr
l (M.Lit (ExactDbl Integer
1)) = ModelExpr
l
  mulRe (M.Lit (ExactDbl Integer
1)) ModelExpr
r = ModelExpr
r
  mulRe (M.AssocA AssocArithOper
M.MulRe [ModelExpr]
l) (M.AssocA AssocArithOper
M.MulRe [ModelExpr]
r) = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.MulRe ([ModelExpr]
l forall a. [a] -> [a] -> [a]
++ [ModelExpr]
r)
  mulRe (M.AssocA AssocArithOper
M.MulRe [ModelExpr]
l) ModelExpr
r = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.MulRe ([ModelExpr]
l forall a. [a] -> [a] -> [a]
++ [ModelExpr
r])
  mulRe ModelExpr
l (M.AssocA AssocArithOper
M.MulRe [ModelExpr]
r) = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.MulRe (ModelExpr
l forall a. a -> [a] -> [a]
: [ModelExpr]
r)
  mulRe ModelExpr
l ModelExpr
r = AssocArithOper -> [ModelExpr] -> ModelExpr
M.AssocA AssocArithOper
M.MulRe [ModelExpr
l, ModelExpr
r]

  -- | Smart constructor for subtracting two expressions.
  $- :: ModelExpr -> ModelExpr -> ModelExpr
($-) = ArithBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.ArithBinaryOp ArithBinOp
M.Subt
  -- | Smart constructor for dividing two expressions.
  $/ :: ModelExpr -> ModelExpr -> ModelExpr
($/) = ArithBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.ArithBinaryOp ArithBinOp
M.Frac
  -- | Smart constructor for rasing the first expression to the power of the second.
  $^ :: ModelExpr -> ModelExpr -> ModelExpr
($^) = ArithBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.ArithBinaryOp ArithBinOp
M.Pow

  -- | Smart constructor to show that one expression implies the other (conditional operator).
  $=> :: ModelExpr -> ModelExpr -> ModelExpr
($=>)  = BoolBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.BoolBinaryOp BoolBinOp
M.Impl
  -- | Smart constructor to show that an expression exists if and only if another expression exists (biconditional operator).
  $<=> :: ModelExpr -> ModelExpr -> ModelExpr
($<=>) = BoolBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.BoolBinaryOp BoolBinOp
M.Iff

  -- | Smart constructor for the boolean /and/ operator.
  ModelExpr
a $&& :: ModelExpr -> ModelExpr -> ModelExpr
$&& ModelExpr
b = AssocBoolOper -> [ModelExpr] -> ModelExpr
M.AssocB AssocBoolOper
M.And [ModelExpr
a, ModelExpr
b]
  -- | Smart constructor for the boolean /or/ operator.
  ModelExpr
a $|| :: ModelExpr -> ModelExpr -> ModelExpr
$|| ModelExpr
b = AssocBoolOper -> [ModelExpr] -> ModelExpr
M.AssocB AssocBoolOper
M.Or  [ModelExpr
a, ModelExpr
b]

  -- | Smart constructor for taking the absolute value of an expression.
  abs_ :: ModelExpr -> ModelExpr
abs_ = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Abs

  -- | Smart constructor for negating an expression.
  neg :: ModelExpr -> ModelExpr
neg = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Neg

  -- | Smart constructor to take the log of an expression.
  log :: ModelExpr -> ModelExpr
log = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Log

  -- | Smart constructor to take the ln of an expression.
  ln :: ModelExpr -> ModelExpr
ln = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Ln

  -- | Smart constructor to take the square root of an expression.
  sqrt :: ModelExpr -> ModelExpr
sqrt = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Sqrt

  -- | Smart constructor to apply sin to an expression.
  sin :: ModelExpr -> ModelExpr
sin = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Sin

  -- | Smart constructor to apply cos to an expression.
  cos :: ModelExpr -> ModelExpr
cos = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Cos

  -- | Smart constructor to apply tan to an expression.
  tan :: ModelExpr -> ModelExpr
tan = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Tan

  -- | Smart constructor to apply sec to an expression.
  sec :: ModelExpr -> ModelExpr
sec = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Sec

  -- | Smart constructor to apply csc to an expression.
  csc :: ModelExpr -> ModelExpr
csc = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Csc

  -- | Smart constructor to apply cot to an expression.
  cot :: ModelExpr -> ModelExpr
cot = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Cot

  -- | Smart constructor to apply arcsin to an expression.
  arcsin :: ModelExpr -> ModelExpr
arcsin = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Arcsin

  -- | Smart constructor to apply arccos to an expression.
  arccos :: ModelExpr -> ModelExpr
arccos = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Arccos

  -- | Smart constructor to apply arctan to an expression.
  arctan :: ModelExpr -> ModelExpr
arctan = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Arctan

  -- | Smart constructor for the exponential (base e) function.
  exp :: ModelExpr -> ModelExpr
exp = UFunc -> ModelExpr -> ModelExpr
M.UnaryOp UFunc
M.Exp

  -- | Smart constructor for calculating the dimension of a vector.
  dim :: ModelExpr -> ModelExpr
dim = UFuncVN -> ModelExpr -> ModelExpr
M.UnaryOpVN UFuncVN
M.Dim

  -- | Smart constructor for calculating the normal form of a vector.
  norm :: ModelExpr -> ModelExpr
norm = UFuncVN -> ModelExpr -> ModelExpr
M.UnaryOpVN UFuncVN
M.Norm

  -- | Smart constructor for negating vectors.
  negVec :: ModelExpr -> ModelExpr
negVec = UFuncVV -> ModelExpr -> ModelExpr
M.UnaryOpVV UFuncVV
M.NegV
  -- | More general scaling
  vScale :: ModelExpr -> ModelExpr -> ModelExpr
vScale = NVVBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.NVVBinaryOp NVVBinOp
M.Scale

  -- | Smart constructor for applying logical negation to an expression.
  not_ :: ModelExpr -> ModelExpr
not_ = UFuncB -> ModelExpr -> ModelExpr
M.UnaryOpB UFuncB
M.Not

  -- | Smart constructor for indexing.
  idx :: ModelExpr -> ModelExpr -> ModelExpr
idx = LABinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.LABinaryOp LABinOp
M.Index

  -- | Integrate over some expression with bounds (∫).
  defint :: Symbol -> ModelExpr -> ModelExpr -> ModelExpr -> ModelExpr
defint Symbol
v ModelExpr
low ModelExpr
high = forall (t :: RTopology).
AssocArithOper
-> DomainDesc t ModelExpr ModelExpr -> ModelExpr -> ModelExpr
M.Operator AssocArithOper
M.AddRe (forall a b.
Symbol -> RTopology -> a -> b -> DomainDesc 'Discrete a b
BoundedDD Symbol
v RTopology
Continuous ModelExpr
low ModelExpr
high)

  -- | Sum over some expression with bounds (∑).
  defsum :: Symbol -> ModelExpr -> ModelExpr -> ModelExpr -> ModelExpr
defsum Symbol
v ModelExpr
low ModelExpr
high = forall (t :: RTopology).
AssocArithOper
-> DomainDesc t ModelExpr ModelExpr -> ModelExpr -> ModelExpr
M.Operator AssocArithOper
M.AddRe (forall a b.
Symbol -> RTopology -> a -> b -> DomainDesc 'Discrete a b
BoundedDD Symbol
v RTopology
Discrete ModelExpr
low ModelExpr
high)

  -- | Product over some expression with bounds (∏).
  defprod :: Symbol -> ModelExpr -> ModelExpr -> ModelExpr -> ModelExpr
defprod Symbol
v ModelExpr
low ModelExpr
high = forall (t :: RTopology).
AssocArithOper
-> DomainDesc t ModelExpr ModelExpr -> ModelExpr -> ModelExpr
M.Operator AssocArithOper
M.MulRe (forall a b.
Symbol -> RTopology -> a -> b -> DomainDesc 'Discrete a b
BoundedDD Symbol
v RTopology
Discrete ModelExpr
low ModelExpr
high)

  -- | Smart constructor for 'real interval' membership.
  realInterval :: forall c.
HasUID c =>
c -> RealInterval ModelExpr ModelExpr -> ModelExpr
realInterval c
c = UID -> RealInterval ModelExpr ModelExpr -> ModelExpr
M.RealI (c
c forall s a. s -> Getting a s a -> a
^. forall c. HasUID c => Lens' c UID
uid)

  -- | Euclidean function : takes a vector and returns the sqrt of the sum-of-squares.
  euclidean :: [ModelExpr] -> ModelExpr
euclidean = forall r. ExprC r => r -> r
sqrt forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 forall r. ExprC r => r -> r -> r
addRe forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall r. (ExprC r, LiteralC r) => r -> r
square

  -- | Smart constructor to cross product two expressions.
  cross :: ModelExpr -> ModelExpr -> ModelExpr
cross = VVVBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.VVVBinaryOp VVVBinOp
M.Cross

  -- | Adding vectors
  vAdd :: ModelExpr -> ModelExpr -> ModelExpr
vAdd  = VVVBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.VVVBinaryOp VVVBinOp
M.VAdd
  -- | Subtracting vectors
  vSub :: ModelExpr -> ModelExpr -> ModelExpr
vSub  = VVVBinOp -> ModelExpr -> ModelExpr -> ModelExpr
M.VVVBinaryOp VVVBinOp
M.VSub
  
  -- | Smart constructor for case statements with a complete set of cases.
  completeCase :: [(ModelExpr, ModelExpr)] -> ModelExpr
completeCase = Completeness -> [(ModelExpr, ModelExpr)] -> ModelExpr
M.Case Completeness
Complete

  -- | Smart constructor for case statements with an incomplete set of cases.
  incompleteCase :: [(ModelExpr, ModelExpr)] -> ModelExpr
incompleteCase = Completeness -> [(ModelExpr, ModelExpr)] -> ModelExpr
M.Case Completeness
Incomplete

  matrix :: [[ModelExpr]] -> ModelExpr
matrix = [[ModelExpr]] -> ModelExpr
M.Matrix

  -- | Applies a given function with a list of parameters.
  apply :: forall f. (HasUID f, HasSymbol f) => f -> [ModelExpr] -> ModelExpr
apply f
f [] = forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy f
f
  apply f
f [ModelExpr]
ps = UID -> [ModelExpr] -> ModelExpr
M.FCall (f
f forall s a. s -> Getting a s a -> a
^. forall c. HasUID c => Lens' c UID
uid) [ModelExpr]
ps

  -- Note how |sy| 'enforces' having a symbol
  -- | Create an 'Expr' from a 'Symbol'ic Chunk.
  sy :: forall c. (HasUID c, HasSymbol c) => c -> ModelExpr
sy c
x = UID -> ModelExpr
M.C (c
x forall s a. s -> Getting a s a -> a
^. forall c. HasUID c => Lens' c UID
uid)

instance ExprC C.CodeExpr where
  lit :: Literal -> CodeExpr
lit = Literal -> CodeExpr
C.Lit

  -- | Smart constructor for equating two expressions.
  $= :: CodeExpr -> CodeExpr -> CodeExpr
($=)  = EqBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.EqBinaryOp EqBinOp
C.Eq
  -- | Smart constructor for showing that two expressions are not equal.
  $!= :: CodeExpr -> CodeExpr -> CodeExpr
($!=) = EqBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.EqBinaryOp EqBinOp
C.NEq
  
  -- | Smart constructor for ordering two equations.
  -- | Less than.
  $< :: CodeExpr -> CodeExpr -> CodeExpr
($<)  = OrdBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.OrdBinaryOp OrdBinOp
C.Lt
  -- | Greater than.
  $> :: CodeExpr -> CodeExpr -> CodeExpr
($>)  = OrdBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.OrdBinaryOp OrdBinOp
C.Gt
  -- | Less than or equal to.
  $<= :: CodeExpr -> CodeExpr -> CodeExpr
($<=) = OrdBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.OrdBinaryOp OrdBinOp
C.LEq
  -- | Greater than or equal to.
  $>= :: CodeExpr -> CodeExpr -> CodeExpr
($>=) = OrdBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.OrdBinaryOp OrdBinOp
C.GEq
  
  -- | Smart constructor for the dot product of two equations.
  $. :: CodeExpr -> CodeExpr -> CodeExpr
($.) = VVNBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.VVNBinaryOp VVNBinOp
C.Dot
  
  -- | Add two expressions (Integers).
  addI :: CodeExpr -> CodeExpr -> CodeExpr
addI CodeExpr
l (C.Lit (Int Integer
0)) = CodeExpr
l
  addI (C.Lit (Int Integer
0)) CodeExpr
r = CodeExpr
r
  addI (C.AssocA AssocArithOper
C.AddI [CodeExpr]
l) (C.AssocA AssocArithOper
C.AddI [CodeExpr]
r) = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.AddI ([CodeExpr]
l forall a. [a] -> [a] -> [a]
++ [CodeExpr]
r)
  addI (C.AssocA AssocArithOper
C.AddI [CodeExpr]
l) CodeExpr
r = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.AddI ([CodeExpr]
l forall a. [a] -> [a] -> [a]
++ [CodeExpr
r])
  addI CodeExpr
l (C.AssocA AssocArithOper
C.AddI [CodeExpr]
r) = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.AddI (CodeExpr
l forall a. a -> [a] -> [a]
: [CodeExpr]
r)
  addI CodeExpr
l CodeExpr
r = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.AddI [CodeExpr
l, CodeExpr
r]
  
  -- | Add two expressions (Real numbers).
  addRe :: CodeExpr -> CodeExpr -> CodeExpr
addRe CodeExpr
l (C.Lit (Dbl Double
0))= CodeExpr
l
  addRe (C.Lit(Dbl Double
0)) CodeExpr
r      = CodeExpr
r
  addRe CodeExpr
l (C.Lit (ExactDbl Integer
0)) = CodeExpr
l
  addRe (C.Lit (ExactDbl Integer
0)) CodeExpr
r = CodeExpr
r
  addRe (C.AssocA AssocArithOper
C.AddRe [CodeExpr]
l) (C.AssocA AssocArithOper
C.AddRe [CodeExpr]
r) = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.AddRe ([CodeExpr]
l forall a. [a] -> [a] -> [a]
++ [CodeExpr]
r)
  addRe (C.AssocA AssocArithOper
C.AddRe [CodeExpr]
l) CodeExpr
r = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.AddRe ([CodeExpr]
l forall a. [a] -> [a] -> [a]
++ [CodeExpr
r])
  addRe CodeExpr
l (C.AssocA AssocArithOper
C.AddRe [CodeExpr]
r) = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.AddRe (CodeExpr
l forall a. a -> [a] -> [a]
: [CodeExpr]
r)
  addRe CodeExpr
l CodeExpr
r = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.AddRe [CodeExpr
l, CodeExpr
r]
  
  -- | Multiply two expressions (Integers).
  mulI :: CodeExpr -> CodeExpr -> CodeExpr
mulI CodeExpr
l (C.Lit (Int Integer
1)) = CodeExpr
l
  mulI (C.Lit (Int Integer
1)) CodeExpr
r = CodeExpr
r
  mulI (C.AssocA AssocArithOper
C.MulI [CodeExpr]
l) (C.AssocA AssocArithOper
C.MulI [CodeExpr]
r) = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.MulI ([CodeExpr]
l forall a. [a] -> [a] -> [a]
++ [CodeExpr]
r)
  mulI (C.AssocA AssocArithOper
C.MulI [CodeExpr]
l) CodeExpr
r = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.MulI ([CodeExpr]
l forall a. [a] -> [a] -> [a]
++ [CodeExpr
r])
  mulI CodeExpr
l (C.AssocA AssocArithOper
C.MulI [CodeExpr]
r) = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.MulI (CodeExpr
l forall a. a -> [a] -> [a]
: [CodeExpr]
r)
  mulI CodeExpr
l CodeExpr
r = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.MulI [CodeExpr
l, CodeExpr
r]
  
  -- | Multiply two expressions (Real numbers).
  mulRe :: CodeExpr -> CodeExpr -> CodeExpr
mulRe CodeExpr
l (C.Lit (Dbl Double
1))      = CodeExpr
l
  mulRe (C.Lit (Dbl Double
1)) CodeExpr
r      = CodeExpr
r
  mulRe CodeExpr
l (C.Lit (ExactDbl Integer
1)) = CodeExpr
l
  mulRe (C.Lit (ExactDbl Integer
1)) CodeExpr
r = CodeExpr
r
  mulRe (C.AssocA AssocArithOper
C.MulRe [CodeExpr]
l) (C.AssocA AssocArithOper
C.MulRe [CodeExpr]
r) = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.MulRe ([CodeExpr]
l forall a. [a] -> [a] -> [a]
++ [CodeExpr]
r)
  mulRe (C.AssocA AssocArithOper
C.MulRe [CodeExpr]
l) CodeExpr
r = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.MulRe ([CodeExpr]
l forall a. [a] -> [a] -> [a]
++ [CodeExpr
r])
  mulRe CodeExpr
l (C.AssocA AssocArithOper
C.MulRe [CodeExpr]
r) = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.MulRe (CodeExpr
l forall a. a -> [a] -> [a]
: [CodeExpr]
r)
  mulRe CodeExpr
l CodeExpr
r = AssocArithOper -> [CodeExpr] -> CodeExpr
C.AssocA AssocArithOper
C.MulRe [CodeExpr
l, CodeExpr
r]
  
  -- | Smart constructor for subtracting two expressions.
  $- :: CodeExpr -> CodeExpr -> CodeExpr
($-) = ArithBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.ArithBinaryOp ArithBinOp
C.Subt
  -- | Smart constructor for dividing two expressions.
  $/ :: CodeExpr -> CodeExpr -> CodeExpr
($/) = ArithBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.ArithBinaryOp ArithBinOp
C.Frac
  -- | Smart constructor for rasing the first expression to the power of the second.
  $^ :: CodeExpr -> CodeExpr -> CodeExpr
($^) = ArithBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.ArithBinaryOp ArithBinOp
C.Pow
  
  -- | Smart constructor to show that one expression implies the other (conditional operator).
  $=> :: CodeExpr -> CodeExpr -> CodeExpr
($=>)  = BoolBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.BoolBinaryOp BoolBinOp
C.Impl
  -- | Smart constructor to show that an expression exists if and only if another expression exists (biconditional operator).
  $<=> :: CodeExpr -> CodeExpr -> CodeExpr
($<=>) = BoolBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.BoolBinaryOp BoolBinOp
C.Iff
  
  -- | Smart constructor for the boolean /and/ operator.
  CodeExpr
a $&& :: CodeExpr -> CodeExpr -> CodeExpr
$&& CodeExpr
b = AssocBoolOper -> [CodeExpr] -> CodeExpr
C.AssocB AssocBoolOper
C.And [CodeExpr
a, CodeExpr
b]
  -- | Smart constructor for the boolean /or/ operator.
  CodeExpr
a $|| :: CodeExpr -> CodeExpr -> CodeExpr
$|| CodeExpr
b = AssocBoolOper -> [CodeExpr] -> CodeExpr
C.AssocB AssocBoolOper
C.Or  [CodeExpr
a, CodeExpr
b]
  
  -- | Smart constructor for taking the absolute value of an expression.
  abs_ :: CodeExpr -> CodeExpr
abs_ = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Abs
  
  -- | Smart constructor for negating an expression.
  neg :: CodeExpr -> CodeExpr
neg = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Neg
  
  -- | Smart constructor to take the log of an expression.
  log :: CodeExpr -> CodeExpr
log = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Log
  
  -- | Smart constructor to take the ln of an expression.
  ln :: CodeExpr -> CodeExpr
ln = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Ln
  
  -- | Smart constructor to take the square root of an expression.
  sqrt :: CodeExpr -> CodeExpr
sqrt = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Sqrt
  
  -- | Smart constructor to apply sin to an expression.
  sin :: CodeExpr -> CodeExpr
sin = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Sin
  
  -- | Smart constructor to apply cos to an expression.
  cos :: CodeExpr -> CodeExpr
cos = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Cos
  
  -- | Smart constructor to apply tan to an expression.
  tan :: CodeExpr -> CodeExpr
tan = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Tan
  
  -- | Smart constructor to apply sec to an expression.
  sec :: CodeExpr -> CodeExpr
sec = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Sec
  
  -- | Smart constructor to apply csc to an expression.
  csc :: CodeExpr -> CodeExpr
csc = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Csc
  
  -- | Smart constructor to apply cot to an expression.
  cot :: CodeExpr -> CodeExpr
cot = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Cot
  
  -- | Smart constructor to apply arcsin to an expression.
  arcsin :: CodeExpr -> CodeExpr
arcsin = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Arcsin
  
  -- | Smart constructor to apply arccos to an expression.
  arccos :: CodeExpr -> CodeExpr
arccos = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Arccos
  
  -- | Smart constructor to apply arctan to an expression.
  arctan :: CodeExpr -> CodeExpr
arctan = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Arctan
  
  -- | Smart constructor for the exponential (base e) function.
  exp :: CodeExpr -> CodeExpr
exp = UFunc -> CodeExpr -> CodeExpr
C.UnaryOp UFunc
C.Exp
  
  -- | Smart constructor for calculating the dimension of a vector.
  dim :: CodeExpr -> CodeExpr
dim = UFuncVN -> CodeExpr -> CodeExpr
C.UnaryOpVN UFuncVN
C.Dim
  
  -- | Smart constructor for calculating the normal form of a vector.
  norm :: CodeExpr -> CodeExpr
norm = UFuncVN -> CodeExpr -> CodeExpr
C.UnaryOpVN UFuncVN
C.Norm
  
  -- | Smart constructor for negating vectors.
  negVec :: CodeExpr -> CodeExpr
negVec = UFuncVV -> CodeExpr -> CodeExpr
C.UnaryOpVV UFuncVV
C.NegV
  -- | And more general scaling
  vScale :: CodeExpr -> CodeExpr -> CodeExpr
vScale = NVVBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.NVVBinaryOp NVVBinOp
C.Scale
  
  -- | Smart constructor for applying logical negation to an expression.
  not_ :: CodeExpr -> CodeExpr
not_ = UFuncB -> CodeExpr -> CodeExpr
C.UnaryOpB UFuncB
C.Not
  
  -- | Smart constructor for indexing.
  idx :: CodeExpr -> CodeExpr -> CodeExpr
idx = LABinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.LABinaryOp LABinOp
C.Index
  
  -- | Integrate over some expression with bounds (∫).
  defint :: Symbol -> CodeExpr -> CodeExpr -> CodeExpr -> CodeExpr
defint Symbol
v CodeExpr
low CodeExpr
high = AssocArithOper
-> DiscreteDomainDesc CodeExpr CodeExpr -> CodeExpr -> CodeExpr
C.Operator AssocArithOper
C.AddRe (forall a b.
Symbol -> RTopology -> a -> b -> DomainDesc 'Discrete a b
BoundedDD Symbol
v RTopology
Continuous CodeExpr
low CodeExpr
high)
  
  -- | Sum over some expression with bounds (∑).
  defsum :: Symbol -> CodeExpr -> CodeExpr -> CodeExpr -> CodeExpr
defsum Symbol
v CodeExpr
low CodeExpr
high = AssocArithOper
-> DiscreteDomainDesc CodeExpr CodeExpr -> CodeExpr -> CodeExpr
C.Operator AssocArithOper
C.AddRe (forall a b.
Symbol -> RTopology -> a -> b -> DomainDesc 'Discrete a b
BoundedDD Symbol
v RTopology
Discrete CodeExpr
low CodeExpr
high)
  
  -- | Product over some expression with bounds (∏).
  defprod :: Symbol -> CodeExpr -> CodeExpr -> CodeExpr -> CodeExpr
defprod Symbol
v CodeExpr
low CodeExpr
high = AssocArithOper
-> DiscreteDomainDesc CodeExpr CodeExpr -> CodeExpr -> CodeExpr
C.Operator AssocArithOper
C.MulRe (forall a b.
Symbol -> RTopology -> a -> b -> DomainDesc 'Discrete a b
BoundedDD Symbol
v RTopology
Discrete CodeExpr
low CodeExpr
high)
  
  -- | Smart constructor for 'real interval' membership.
  realInterval :: forall c.
HasUID c =>
c -> RealInterval CodeExpr CodeExpr -> CodeExpr
realInterval c
c = UID -> RealInterval CodeExpr CodeExpr -> CodeExpr
C.RealI (c
c forall s a. s -> Getting a s a -> a
^. forall c. HasUID c => Lens' c UID
uid)
  
  -- | Euclidean function : takes a vector and returns the sqrt of the sum-of-squares.
  euclidean :: [CodeExpr] -> CodeExpr
euclidean = forall r. ExprC r => r -> r
sqrt forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 forall r. ExprC r => r -> r -> r
addRe forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall r. (ExprC r, LiteralC r) => r -> r
square
  
  -- | Smart constructor to cross product two expressions.
  cross :: CodeExpr -> CodeExpr -> CodeExpr
cross = VVVBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.VVVBinaryOp VVVBinOp
C.Cross
  
  -- | Adding vectors
  vAdd :: CodeExpr -> CodeExpr -> CodeExpr
vAdd  = VVVBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.VVVBinaryOp VVVBinOp
C.VAdd
  -- | Subtracting vectors
  vSub :: CodeExpr -> CodeExpr -> CodeExpr
vSub  = VVVBinOp -> CodeExpr -> CodeExpr -> CodeExpr
C.VVVBinaryOp VVVBinOp
C.VSub

  -- | Smart constructor for case statements with a complete set of cases.
  completeCase :: [(CodeExpr, CodeExpr)] -> CodeExpr
completeCase = Completeness -> [(CodeExpr, CodeExpr)] -> CodeExpr
C.Case Completeness
Complete
  
  -- | Smart constructor for case statements with an incomplete set of cases.
  incompleteCase :: [(CodeExpr, CodeExpr)] -> CodeExpr
incompleteCase = Completeness -> [(CodeExpr, CodeExpr)] -> CodeExpr
C.Case Completeness
Incomplete
  
  matrix :: [[CodeExpr]] -> CodeExpr
matrix = [[CodeExpr]] -> CodeExpr
C.Matrix

  -- | Applies a given function with a list of parameters.
  apply :: forall f. (HasUID f, HasSymbol f) => f -> [CodeExpr] -> CodeExpr
apply f
f [] = forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy f
f
  apply f
f [CodeExpr]
ps = UID -> [CodeExpr] -> [(UID, CodeExpr)] -> CodeExpr
C.FCall (f
f forall s a. s -> Getting a s a -> a
^. forall c. HasUID c => Lens' c UID
uid) [CodeExpr]
ps []
  
  -- Note how |sy| 'enforces' having a symbol
  -- | Create an 'Expr' from a 'Symbol'ic Chunk.
  sy :: forall c. (HasUID c, HasSymbol c) => c -> CodeExpr
sy c
x = UID -> CodeExpr
C.C (c
x forall s a. s -> Getting a s a -> a
^. forall c. HasUID c => Lens' c UID
uid)