--
--
-- Integration
--
--

Sd x f :=
  match f as mathExpr with
    -- symbols
    | #x -> 1 / 2 * x ^ 2
    | symbol _ _ -> f * x
    -- function application
    | #exp #x -> exp x
    | #cos #x -> sin x
    | #sin #x -> - cos x
    | #log #x -> multSd x 1 (log x)
    | #(^) $a #x -> a ^ x / log a
    | #(^) $a $y ->
      withSymbols [t] substitute [(t, y)] (Sd t (a ^ t * d/d (inverse t y x) t))
    | #Sd $y $g -> `Sd x (`Sd y g)
    | $f $y ->
      withSymbols [t] substitute [(t, y)] (Sd t (f t * d/d (inverse t y x) t))
    -- term (constant)
    | #0 -> 0
    | term $c [] -> c * x
    -- term (multiplication)
    | mult $a (ncons $n #x $r) ->
      if containSymbol x r then `Sd x f else a / (n + 1) * x ^ (n + 1) * r
    -- polynomial
    | poly $ts -> sum (map 1#(Sd x %1) ts)
    -- quotient
    | (plus $ts) / $p2 -> sum (map 1#(Sd x (%1 / p2)) ts)
    | $p1 / $p2 -> if containSymbol x p2 then `Sd x f else Sd x p1 / p2

multSd x f g :=
  let F := Sd x f
   in F * g - Sd x (F * d/d g x)

dSd x a b f :=
  let F := Sd x f
   in substitute [(x, b)] F - substitute [(x, a)] F
