%mathpiper,def="GetNumerDenom"

/// GetNumerDenom(x) returns a pair of expressions representing normalized numerator and denominator; GetNumerDenom(x, a) multiplies the numerator by the number a
GetNumerDenom(_expr, _a) <-- GetNumerDenom(expr)*{a,1};

// on expressions that are not fractions, we return unit denominator
10 # GetNumerDenom(_expr)_Not(HasFuncSome(expr, "/", {ToAtom("+"), ToAtom("-"), *, /, ^})) <-- {expr, 1};
// rational numbers are not simplified
15 # GetNumerDenom(a_IsRationalOrNumber) <-- {a, 1};
// arithmetic
20 # GetNumerDenom(_a + _b) <-- ExpandFrac'add(GetNumerDenom(a), GetNumerDenom(b));
20 # GetNumerDenom(_a - _b) <-- ExpandFrac'add(GetNumerDenom(a), GetNumerDenom(b, -1));
20 # GetNumerDenom(- _a) <-- GetNumerDenom(a, -1);
20 # GetNumerDenom(+ _a) <-- GetNumerDenom(a);
20 # GetNumerDenom(_a * _b) <-- ExpandFrac'multiply(GetNumerDenom(a), GetNumerDenom(b));
20 # GetNumerDenom(_a / _b) <-- ExpandFrac'divide(GetNumerDenom(a), GetNumerDenom(b));
// integer powers
20 # GetNumerDenom(_a ^ b_IsInteger)_(b > 1) <-- ExpandFrac'multiply(GetNumerDenom(a), GetNumerDenom(a^(b-1)));
20 # GetNumerDenom(_a ^ b_IsInteger)_(b < -1) <-- ExpandFrac'divide(GetNumerDenom(1), GetNumerDenom(a^(-b)));
20 # GetNumerDenom(_a ^ b_IsInteger)_(b = -1) <-- ExpandFrac'divide(GetNumerDenom(1), GetNumerDenom(a));
// non-integer powers are not considered to be rational functions
25 # GetNumerDenom(_a ^ _b) <-- {a^b, 1};

// arithmetic on fractions; not doing any simplification here, whereas we might want to
ExpandFrac'add({_a, _b}, {_c, _d}) <-- {a*d+b*c, b*d};
ExpandFrac'multiply({_a, _b}, {_c, _d}) <-- {a*c, b*d};
ExpandFrac'divide({_a, _b}, {_c, _d}) <-- {a*d, b*c};

%/mathpiper