-- |
-- Module: Symtegtarion.Symbolic.Simplify.Tidy
-- Description: Tidy up a simplified mathematical expression.
-- Copyright: Copyright 2025 Yoo Chung
-- License: Apache-2.0
-- Maintainer: dev@chungyc.org
module Symtegration.Symbolic.Simplify.Tidy (tidy) where

import Symtegration.Symbolic

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

-- | Tidies up expressions for nicer output.
--
-- Assumes that other simplifications have been applied first.
-- In fact, it may undo changes that made other simplifications easier.
--
-- ==== __What is tidied up__
--
-- This section shows examples of what this function tidies up.
--
-- >>> toHaskell $ tidy $ "x" + negate "y"
-- "x - y"
--
-- >>> toHaskell $ tidy $ "x" + Number (-2) * "y"
-- "x - 2 * y"
--
-- >>> toHaskell $ tidy $ Number (-1) / Number 2
-- "negate (1 / 2)"
--
-- >>> toHaskell $ tidy $ Number (-1) * "x"
-- "negate x"
--
-- >>> toHaskell $ tidy $ (-"x") * "y"
-- "negate (x * y)"
--
-- >>> toHaskell $ tidy $ "x" * (-"y")
-- "negate (x * y)"
--
-- >>> toHaskell $ tidy $ (-"x") * (-"y")
-- "x * y"
--
-- >>> toHaskell $ tidy $ "x" + ((-"y") + "z")
-- "x - y + z"
tidy :: Expression -> Expression
tidy :: Expression -> Expression
tidy (UnaryApply UnaryFunction
func Expression
x) = Expression -> Expression
unary (Expression -> Expression) -> Expression -> Expression
forall a b. (a -> b) -> a -> b
$ UnaryFunction -> Expression -> Expression
UnaryApply UnaryFunction
func (Expression -> Expression) -> Expression -> Expression
forall a b. (a -> b) -> a -> b
$ Expression -> Expression
tidy Expression
x
tidy (BinaryApply BinaryFunction
func Expression
x Expression
y) = Expression -> Expression
binary (Expression -> Expression) -> Expression -> Expression
forall a b. (a -> b) -> a -> b
$ BinaryFunction -> Expression -> Expression -> Expression
BinaryApply BinaryFunction
func (Expression -> Expression
tidy Expression
x) (Expression -> Expression
tidy Expression
y)
tidy Expression
e = Expression
e

unary :: Expression -> Expression
unary :: Expression -> Expression
unary Expression
e = Expression
e

binary :: Expression -> Expression
binary :: Expression -> Expression
binary (Expression
x :+: (Negate' Expression
y)) = Expression
x Expression -> Expression -> Expression
:-: Expression
y
binary (Number (-1) :*: Expression
x) = Expression -> Expression
Negate' Expression
x
binary e :: Expression
e@(Number Integer
n :*: Expression
x)
  | Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 = Expression -> Expression
Negate' (Integer -> Expression
Number (-Integer
n) Expression -> Expression -> Expression
:*: Expression
x)
  | Bool
otherwise = Expression
e
binary e :: Expression
e@(Number Integer
n :/: Expression
x)
  | Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 = Expression -> Expression
Negate' (Integer -> Expression
Number (-Integer
n) Expression -> Expression -> Expression
:/: Expression
x)
  | Bool
otherwise = Expression
e
binary (Negate' Expression
x :*: Negate' Expression
y) = Expression
x Expression -> Expression -> Expression
:*: Expression
y
binary (Negate' Expression
x :*: Expression
y) = Expression -> Expression
Negate' (Expression -> Expression) -> Expression -> Expression
forall a b. (a -> b) -> a -> b
$ Expression
x Expression -> Expression -> Expression
:*: Expression
y
binary (Expression
x :*: Negate' Expression
y) = Expression -> Expression
Negate' (Expression -> Expression) -> Expression -> Expression
forall a b. (a -> b) -> a -> b
$ Expression
x Expression -> Expression -> Expression
:*: Expression
y
binary (Expression
x :+: (Negate' Expression
y :+: Expression
z)) = (Expression
x Expression -> Expression -> Expression
:-: Expression
y) Expression -> Expression -> Expression
:+: Expression
z
binary Expression
e = Expression
e