Some checks are pending
CI / Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} (x64, ubuntu-latest, 1.6) (push) Waiting to run
CI / Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} (x64, ubuntu-latest, pre) (push) Waiting to run
CI / Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} (x64, ubuntu-latest, 1.10) (push) Waiting to run
140 lines
3.9 KiB
Julia
140 lines
3.9 KiB
Julia
module ExpressionProcessing
|
|
|
|
export expr_to_postfix, is_binary_operator
|
|
export PostfixType
|
|
export Operator, ADD, SUBTRACT, MULTIPLY, DIVIDE, POWER, ABS, LOG, EXP, SQRT
|
|
export ElementType, EMPTY, FLOAT32, OPERATOR, INDEX
|
|
export ExpressionElement
|
|
|
|
@enum Operator ADD=1 SUBTRACT=2 MULTIPLY=3 DIVIDE=4 POWER=5 ABS=6 LOG=7 EXP=8 SQRT=9
|
|
@enum ElementType EMPTY=0 FLOAT32=1 OPERATOR=2 INDEX=3
|
|
|
|
struct ExpressionElement
|
|
Type::ElementType
|
|
Value::Int32 # Reinterpret the stored value to type "ElementType" when using it
|
|
end
|
|
|
|
const PostfixType = Vector{ExpressionElement}
|
|
|
|
"
|
|
Converts a julia expression to its postfix notation.
|
|
NOTE: All 64-Bit values will be converted to 32-Bit. Be aware of the lost precision
|
|
"
|
|
function expr_to_postfix(expr::Expr)::PostfixType
|
|
postfix = PostfixType()
|
|
@inbounds operator = get_operator(expr.args[1])
|
|
|
|
@inbounds for j in 2:length(expr.args)
|
|
arg = expr.args[j]
|
|
|
|
if typeof(arg) === Expr
|
|
append!(postfix, expr_to_postfix(arg))
|
|
elseif typeof(arg) === Symbol # variables/parameters
|
|
# maybe TODO: replace the parameters with their respective values, as this might make the expr evaluation faster
|
|
exprElement = convert_to_ExpressionElement(convert_var_to_int(arg))
|
|
push!(postfix, exprElement)
|
|
else
|
|
exprElement = convert_to_ExpressionElement(convert(Float32, arg))
|
|
push!(postfix, exprElement)
|
|
end
|
|
|
|
# only add operator if at least 2 values are added. For the case where another expression is added first, we check if we are at the first iteration or not ( j != 2)
|
|
if length(postfix) >= 2 && j != 2
|
|
exprElement = convert_to_ExpressionElement(operator)
|
|
push!(postfix, exprElement)
|
|
end
|
|
end
|
|
|
|
# For the case this expression has an operator that only takes in a single value like "abs(x)"
|
|
if length(postfix) == 1
|
|
push!(postfix, convert_to_ExpressionElement(operator))
|
|
end
|
|
return postfix
|
|
end
|
|
|
|
function get_operator(op::Symbol)::Operator
|
|
if op == :+
|
|
return ADD
|
|
elseif op == :-
|
|
return SUBTRACT
|
|
elseif op == :*
|
|
return MULTIPLY
|
|
elseif op == :/
|
|
return DIVIDE
|
|
elseif op == :^
|
|
return POWER
|
|
elseif op == :abs
|
|
return ABS
|
|
elseif op == :log
|
|
return LOG
|
|
elseif op == :exp
|
|
return EXP
|
|
elseif op == :sqrt
|
|
return SQRT
|
|
elseif op == :powabs
|
|
return POWER # TODO: Fix this
|
|
else
|
|
throw("Operator unknown")
|
|
end
|
|
end
|
|
|
|
"Extracts the number from a variable/parameter and returns it. If the symbol is a parameter ```pn```, the resulting value will be negativ.
|
|
|
|
```x0 and p0``` are not allowed."
|
|
function convert_var_to_int(var::Symbol)::Int32
|
|
varStr = String(var)
|
|
number = parse(Int32, SubString(varStr, 2))
|
|
|
|
if varStr[1] == 'p'
|
|
number = -number
|
|
end
|
|
|
|
return number
|
|
end
|
|
|
|
function convert_to_ExpressionElement(element::Int32)::ExpressionElement
|
|
value = reinterpret(Int32, element)
|
|
return ExpressionElement(INDEX, value)
|
|
end
|
|
function convert_to_ExpressionElement(element::Int64)::ExpressionElement
|
|
value = reinterpret(Int32, convert(Int32, element))
|
|
return ExpressionElement(INDEX, value)
|
|
end
|
|
function convert_to_ExpressionElement(element::Float32)::ExpressionElement
|
|
value = reinterpret(Int32, element)
|
|
return ExpressionElement(FLOAT32, value)
|
|
end
|
|
function convert_to_ExpressionElement(element::Float64)::ExpressionElement
|
|
value = reinterpret(Int32, convert(Float32, element))
|
|
return ExpressionElement(FLOAT32, value)
|
|
end
|
|
function convert_to_ExpressionElement(element::Operator)::ExpressionElement
|
|
value = reinterpret(Int32, element)
|
|
return ExpressionElement(OPERATOR, value)
|
|
end
|
|
|
|
function is_binary_operator(operator::Operator)::Bool
|
|
if operator == ADD
|
|
return true
|
|
elseif operator == SUBTRACT
|
|
return true
|
|
elseif operator == MULTIPLY
|
|
return true
|
|
elseif operator == DIVIDE
|
|
return true
|
|
elseif operator == POWER
|
|
return true
|
|
elseif operator == ABS
|
|
return false
|
|
elseif operator == LOG
|
|
return false
|
|
elseif operator == EXP
|
|
return false
|
|
elseif operator == SQRT
|
|
return false
|
|
else
|
|
throw(ArgumentError("Unknown operator '$operator'. Cannot determine if it is binary or not."))
|
|
end
|
|
end
|
|
|
|
end |