/** This contains functions for formatting equations into a traditional form, notably putting numerators above denominators in the result. For example, this turns a d^-2 (b + e)^-1 to a ────────── d² (b + e) Or the continued fraction: f = noEval[a0 + b1 / (a1 + b2/(a2 + b3/(a3 + b4/(a4 + x))))] formatExpression[f] to b1 ───────────────────── b2 ──────────────── a0 + b3 a1 + ─────────── a2 + b4 a3 + ────── a4 + x This will hopefully be put into Frink as a new formatter. TODO: Try to align vertically along midlines? */ /** Formats an expression. This dispatches to the appropriate formatter for the expression type and is generally called recursively. */ formatExpression[eq] := { /* First, determine if an expression can be broken into a numerator and denominator. If the denominator is not 1, this means that it can be broken up. This takes care of division, exponentiation by negative exponents, fractions, and more. This formats into a vertically-separated fraction divided by a horizontal line. */ [num, denom] = frac = numeratorDenominator[eq] if denom != 1 return formatTable[[formatExpression[num], formatExpression[denom]], "center", "center", "\u2500"] type = type[eq] if type == "Add" return formatAdd[eq] if type == "Multiply" return formatMultiply[eq] if type == "Power" return formatPower[eq] if type == "FunctionCall" return formatFunctionCall[eq] /** Handle other operators. This should probably be extended to all operator types like <=, >=, >, etc. However, some operators have other than 2 children and formatOperator currently only handles two-argument infix operators. */ if isOperator[eq] { op = getOperatorSymbol[eq] if op == " === " or op == " = " or op == " -> " return formatOperator[eq] } return eq } // Formats an addition expression to separate fractions. formatAdd[eq] := { size = getChildCount[eq] parts = new array for i=0 to size-1 { child = getChild[eq,i] if type[child] == "Multiply" and isNegativeUnit[getChild[child,0]] { parts.push["-"] child = -child } else if i > 0 parts.push["+"] // Format lower-precedence children in parentheses ep = getOperatorPrecedence[child] expF = formatExpression[child] if ep != undef and ep < getOperatorPrecedence[eq] expF = formatParensCompact[expF] parts.push[expF] } // Format the table into horizontally-separated sums. return formatTable[[parts]] } // Formats a multiplication expression. formatMultiply[eq] := { size = getChildCount[eq] parts = new array for i=0 to size-1 { child = getChild[eq,i] // Format lower-precedence children in parentheses ep = getOperatorPrecedence[child] expF = formatExpression[child] if ep != undef and ep < getOperatorPrecedence[eq] expF = formatParensCompact[expF] parts.push[expF] } // Format the table into horizontally-separated sums with implicit operators return formatTable[[parts]] } // Formats a power expression with raised exponent. formatPower[eq] := { base = getChild[eq,0] exp = getChild[eq,1] separate = false // Format lower-precedence children in parentheses baseF = formatExpression[base] bp = getOperatorPrecedence[base] if bp != undef and bp < getOperatorPrecedence[eq] baseF = formatParensCompact[baseF] /* If the exponent is an integer, format it inline as Unicode superscript digits. */ if isInteger[exp] expF = toUnicodeSuperscript[exp] else { expF = formatExpression[exp] separate = true } ep = getOperatorPrecedence[exp] if ep != undef and ep < getOperatorPrecedence[eq] expF = formatParensCompact[expF] if separate return formatTable[[["",expF],[baseF,""]], "center", "top", "", ""] else return formatTable[[[baseF,expF]], "center", "top", "", ""] } // Formats a function call in mathematical notation. formatFunctionCall[eq] := { args = new array for i = 1 to getChildCount[eq]-1 { if i > 1 args.push[", "] args.push[formatExpression[getChild[eq,i]]] } return formatTable[[[getChild[eq,0], formatBracketsCompact[[args]]]], "", "","", "" ] } // Format operator that has 2 children and is infix. formatOperator[eq] := { left = getChild[eq,0] right = getChild[eq,1] leftF = formatExpression[left] rightF = formatExpression[right] // Format lower-precedence children in parentheses lp = getOperatorPrecedence[left] if lp != undef and lp < getOperatorPrecedence[eq] leftF = formatParensCompact[leftF] rp = getOperatorPrecedence[right] if rp != undef and rp < getOperatorPrecedence[eq] rightF = formatParensCompact[rightF] return formatTable[[[leftF, getOperatorSymbol[eq], rightF]], "", "", "", ""] }