-- |
-- Module: Symtegration.Integration.Powers
-- Description: Integration of arbitrary powers of a variable.
-- Copyright: Copyright 2024 Yoo Chung
-- License: Apache-2.0
-- Maintainer: dev@chungyc.org
module Symtegration.Integration.Powers (integrate) where

import Data.Text (Text)
import Symtegration.Symbolic

-- $setup
-- >>> import Symtegration.Symbolic.Haskell
-- >>> import Symtegration.Symbolic.Simplify

-- | Integrates powers of a variable.
-- In other words, expressions of the form \(x^c\),
-- where \(c\) is a constant.
--
-- >>> toHaskell . simplify <$> integrate "x" "x"
-- Just "1 / 2 * x ** 2"
-- >>> toHaskell . simplify <$> integrate "x" ("x" ** (1/2))
-- Just "(2 * x ** (3 / 2)) / 3"
-- >>> toHaskell . simplify <$> integrate "x" ("x" ** (-1))
-- Just "log x"
integrate :: Text -> Expression -> Maybe Expression
integrate :: Text -> Expression -> Maybe Expression
integrate Text
v (Expression
1 :/: Symbol Text
s) =
  Text -> Expression -> Maybe Expression
integrate Text
v (Expression -> Maybe Expression) -> Expression -> Maybe Expression
forall a b. (a -> b) -> a -> b
$ Text -> Expression
Symbol Text
s Expression -> Expression -> Expression
:**: Integer -> Expression
Number (-Integer
1)
integrate Text
v (Expression
x :**: (Negate' (Number Integer
n :/: Number Integer
m))) =
  Text -> Expression -> Maybe Expression
integrate Text
v (Expression -> Maybe Expression) -> Expression -> Maybe Expression
forall a b. (a -> b) -> a -> b
$ Expression
x Expression -> Expression -> Expression
:**: (Integer -> Expression
Number (-Integer
n) Expression -> Expression -> Expression
:/: Integer -> Expression
Number Integer
m)
integrate Text
v (Expression
x :**: (Negate' (Number Integer
n))) =
  Text -> Expression -> Maybe Expression
integrate Text
v (Expression -> Maybe Expression) -> Expression -> Maybe Expression
forall a b. (a -> b) -> a -> b
$ Expression
x Expression -> Expression -> Expression
:**: Integer -> Expression
Number (-Integer
n)
integrate Text
v e :: Expression
e@(Number Integer
_) = Expression -> Maybe Expression
forall a. a -> Maybe a
Just (Expression -> Maybe Expression) -> Expression -> Maybe Expression
forall a b. (a -> b) -> a -> b
$ Expression
e Expression -> Expression -> Expression
:*: Text -> Expression
Symbol Text
v
integrate Text
v e :: Expression
e@(Symbol Text
v')
  | Text
v Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
v' = Expression -> Maybe Expression
forall a. a -> Maybe a
Just (Expression -> Maybe Expression) -> Expression -> Maybe Expression
forall a b. (a -> b) -> a -> b
$ (Integer -> Expression
Number Integer
1 Expression -> Expression -> Expression
:/: Integer -> Expression
Number Integer
2) Expression -> Expression -> Expression
:*: (Expression
e Expression -> Expression -> Expression
:**: Expression
2)
  | Bool
otherwise = Expression -> Maybe Expression
forall a. a -> Maybe a
Just (Expression -> Maybe Expression) -> Expression -> Maybe Expression
forall a b. (a -> b) -> a -> b
$ Expression
e Expression -> Expression -> Expression
:*: Text -> Expression
Symbol Text
v
integrate Text
v (x :: Expression
x@(Symbol Text
s) :**: Number Integer
n)
  | Text
s Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
v, -1 <- Integer
n = Expression -> Maybe Expression
forall a. a -> Maybe a
Just (Expression -> Maybe Expression) -> Expression -> Maybe Expression
forall a b. (a -> b) -> a -> b
$ Expression -> Expression
Log' Expression
x
  | Text
s Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
v = Expression -> Maybe Expression
forall a. a -> Maybe a
Just (Expression -> Maybe Expression) -> Expression -> Maybe Expression
forall a b. (a -> b) -> a -> b
$ (Expression
x Expression -> Expression -> Expression
:**: Integer -> Expression
Number (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1)) Expression -> Expression -> Expression
:/: Integer -> Expression
Number (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1)
  | Bool
otherwise = Maybe Expression
forall a. Maybe a
Nothing
integrate Text
_ (Expression
_ :**: (Expression
_ :/: Number Integer
0)) = Maybe Expression
forall a. Maybe a
Nothing
integrate Text
v (x :: Expression
x@(Symbol Text
s) :**: y :: Expression
y@(Number Integer
_ :/: Number Integer
_))
  | Text
s Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
v = Expression -> Maybe Expression
forall a. a -> Maybe a
Just (Expression -> Maybe Expression) -> Expression -> Maybe Expression
forall a b. (a -> b) -> a -> b
$ (Expression
x Expression -> Expression -> Expression
:**: (Expression
y Expression -> Expression -> Expression
:+: Expression
1)) Expression -> Expression -> Expression
:/: (Expression
y Expression -> Expression -> Expression
:+: Expression
1)
  | Bool
otherwise = Maybe Expression
forall a. Maybe a
Nothing
integrate Text
_ Expression
_ = Maybe Expression
forall a. Maybe a
Nothing