## 62 Package format ¶

### 62.1 Introduction to format ¶

The `format` package was written by Bruce R. Miller, NIST (miller-at-cam.nist.gov).

`format` is a package for formatting algebraic expressions in Maxima. It provides facilities for user-directed hierarchical structuring of expressions, as well as for directing simplifications to selected subexpressions. It emphasizes a semantic rather than syntactic description of the desired form. The package also provides utilities for obtaining efficiently the coefficients of polynomials, trigonometric sums and power series.

In a general purpose Computer Algebra System (CAS), any particular mathematical expression can take on a variety of forms: expanded form, factored form or anything in between. Each form may have advantages; a given form may be more compact than another, or allow clear expression of certain algorithms. Or it may simply be more informative, particularly if it has physical significance. A CAS contains many tools for transforming expressions. However, most are like Maxima’s `factor` and `expand`, operating only on the entire expression or its top level. At the other extreme are operations like `substpart` which extract a specific part of an expression, then transform and replace it. Unfortunately, the means of specifying the piece of interest is purely syntactic, requiring the user to keep close watch on the form of the arguments to avoid error.

The package described here gives users of Maxima more control over the structure of expressions, and it does so using a more semantic, almost algebraic, language describing the desired structure. It also provides a semantic means of addressing parts of an expression for particular simplifications. For example, to rearrange an expression into a series in `eps` through order 5, whose terms will be polynomials in `x` and `y`, whose coefficients, in turn, will be trigonometric sums in `l` and `g` with factored coefficients one uses the command:

`format(foo; %series(eps; 5); %poly(x; y);%trig(l; g); %factor);`

The principal tool, `format`, is described in section Functions and Variables for format. It uses procedures in `coeflist` which obtain coefficients of polynomials, trigonometric sums and power series.

### 62.2 Functions and Variables for format ¶

Function: format (expr, template1, ...) ¶

  Each `template` indicates the desired form for an expression; either the expected form or that into which it will be transformed. At the same time, the indicated form implies a set of pieces; the next template in the chain applies to those pieces. For example, `%poly(x)` specifies the transformation into a polynomial in `x`, with the pieces being the coefficients. The passive `%frac` treats the expression as a fraction; the pieces are the numerator and denominator. Whereas the next template formats all pieces of the previous layer, positional subtemplates may be used to specify formats for each piece individually. This is most useful when the pieces have unique roles and need to be treated differently, such as a fraction’s numerator and denominator.

The full syntax of a template is

`keyword (parameter ; ...)[subtemplate ; ...]`

The recognized keywords are described below under Template keywords. The parameters (if not needed) and subtemplates (along with parentheses and brackets) are optional.

In addition to the keyword templates, arithmetic patterns are recognized. This is an expression involving addition, multiplication and exponentiation containing a single instance of a keyword template. In effect, the system ‘solves’ the expression to be formatted for the corresponding part, formats it accordingly and reinserts it. For example, `format(X,a+%factor)` is equivalent to `a+factor(X-a)`. Any other template is assumed to be a function to be applied to the expression; the result is then formatted according to the rest of the template chain.

Examples for general restructuring:

    (%i1) load("format")$

    (%i2) format((a+b*x)*(c-x)^2,%poly(x),factor);
                3                2                        2
    (%o2)    b x  - (2 b c - a) x  + c (b c - 2 a) x + a c

    (%i3) format((1+2*eps*(q+r*cos(g))^2)^4,%series(eps,2),%trig(g),factor);
                       2      2                2
    (%o3) 1 + eps (4 (r  + 2 q ) + 4 cos(2 g) r  + 16 cos(g) q r)
          2        4       2  2      4                4
     + eps  (3 (3 r  + 24 q  r  + 8 q ) + 3 cos(4 g) r
                      3                     2      2
     + 24 cos(3 g) q r  + 24 cos(g) q r (3 r  + 4 q )
                    2   2      2
     + 12 cos(2 g) r  (r  + 6 q )) + . . .

    (%i4) format((1+2*a+a^2)*b + a*(1+2*b+b^2),%sum,%product,%factor);
                                  2          2
    (%o4)                a (b + 1)  + (a + 1)  b

    (%i5) format(expand((a+x)^3-a^3),%f-a^3);
                                     3    3
    (%o5)                     (x + a)  - a

#### 62.2.1 Template keywords ¶

Keywords come in several classes: Algebraic, Sums, Products, Fractions, Complex, Bags, General, Targeting, Control, Subtemplate Aids, and Convenience.

A few remarks about keywords: A passive keyword does not transform the expression but treats it as a sum, fraction or whatever. The order of the pieces corresponds to the internal ordering; subtemplate usage may be awkward. See the documentation of `coerce_bag` for a description of the coercions used. Targeting templates are basically shorthand equivalents of structuring templates using subtemplates.

Template(w/abbrev.) | Coersion to | Pieces and Ordering
--- | --- | ---
Class: Algebraic |  |
`%poly(x1,...), %p` | polynomial in xi | coefficients (ascending exps.)
`%series(eps,n), %s` | series in eps through order n | coefficients (ascending exps.)
`%Taylor(eps,n)` | Taylor in eps through order n | coefficients (ascending exps.)
`%monicpoly(x1,...),%mp` | monic polynomial in xi | leading coef then coefs
`%trig(x1,...), %t` | trigonometric sum in xi | `sin` coefs (ascending), then `cos`
`%coeff(v,n)` | polynomial in v | coefficient of vn and remainder

Template(w/abbrev.) | Coersion to | Pieces and Ordering
--- | --- | ---
Class: Sums |  |
`%sum` | passive | terms (`inpart` order)
`%partfrac(x), %pf` | partial fraction decomp in x | terms (`inpart` order)

Template(w/abbrev.) | Coersion to | Pieces and Ordering
--- | --- | ---
Class: Products |  |
`%product, %prod` | passive | factors (`inpart` order)
`%factor, %f` | factored form | factors (`inpart` order)
`%factor(minpoly), %f` | factored with element adjoined | factors (`inpart` order)
`%sqfr, %sf` | square-free factored form | factors (`inpart` order)

Template(w/abbrev.) | Coersion to | Pieces and Ordering
--- | --- | ---
Class: Fractions |  |
`%frac` | passive | numerator and denominator
`%ratsimp, %r` | rationally simplified | numerator and denominator

Template(w/abbrev.) | Coersion to | Pieces and Ordering
--- | --- | ---
Class: Complex |  |
`%rectform, %g` | gaussian form | real and imaginary parts
`%polarform` | polar form | magnitude and phase

Template(w/abbrev.) | Coersion to | Pieces and Ordering
--- | --- | ---
Class: Bags |  |
`%equation, %eq` | equation | l.h.s. and r.h.s.
`%relation(r), %rel` | relation; r in `(=,>,>=,<,<=,!=)` | l.h.s. and r.h.s.
`%list` | list | elements
`%matrix` | matrix | rows (use `%list` for elements)

Template(w/abbrev.) | Coersion to | Pieces and Ordering
--- | --- | ---
Class: General |  |
`%expression, %expr` | passive | the operands (`inpart` order)
`%preformat(T1,...)` | format accord. to chain Ti | the result, not the parts

Template(w/abbrev.) | Function
--- | ---
Class: Targeting |
`%arg(n)` | formats the `n`-th argument
`%lhs(r)` | formats the l.h.s. of an eqn. or relation (default ’=’)
`%rhs(r)` | formats the l.h.s. of an eqn.
`%element(i,...), %el` | formats an element of a matrix
`%num, %denom` | formats the numerator or denominator of a fraction
`%match(P)` | formats all subexpressions for which P(expr) returns true

Template(w/abbrev.) | Function
--- | ---
Class: Control |
`%if(P1,...)[T1,...,Tn+1]` | Find first Pi(expr) → `true`, then format expr using Ti, else Tn+1

Template(w/abbrev.) | Function
--- | ---
Class: Subtemplate Aids |
`%noop` | does nothing; used to fill a subtemplate slot
`[T1,T2,...]` | creates a template chain where an individual template was expected
`%ditto(T)` | repeats the template so that it applies to following pices

Template(w/abbrev.) | Function
--- | ---
Class: Convenience |
`%subst(eqns,...)` | substitutes eqns into expression; result is formatted at next layer
`%ratsubst(eqns,...)` | `lratsubst`’s eqns into expression; result is formatted at next layer

Example with simplification on subexpression:

    (%i1) load("format")$
    (%i2) foo:x^2*sin(y)^4-2*x^2*sin(y)^2+x^4*cos(y)^4-2*x^4*cos(y)^2+x^4+x^2+1$

    (%i3) trigsimp(foo);
                  4    2     4         4    2       4
    (%o3)       (x  + x ) cos (y) - 2 x  cos (y) + x  + 1

    (%i4) format(foo,%p(x),trigsimp);
                        4    4       2    4
    (%o4)              x  sin (y) + x  cos (y) + 1

    (%i5) format([a=b,c=d,e=f],%equation);
    (%o5)                 [a, c, e] = [b, d, f]

    (%i6) format(%,%list);
    (%o6)                 [a = b, c = d, e = f]

    (%i7) m1:matrix([a^2+2*a+1=q,b^2+2*b+1=r], [c^2+2*c+1=s,d^2+2*d+1=t])$

    (%i8) format(m1,%equation,%matrix[%noop,%list[%noop,%factor]]);
                [  2             2           ]
                [ a  + 2 a + 1  b  + 2 b + 1 ]   [ q  r ]
    (%o8)       [                            ] = [      ]
                [  2                     2   ]   [ s  t ]
                [ c  + 2 c + 1    (d + 1)    ]

The following examples illustrate the usage with ‘bags.’

    (%i1) format([a=b,c=d,e=f],%equation);
    (%o1) [a, c, e] = [b, d, f]
    (%i2) format(%,%list);
    (%o2) [a = b, c = d, e = f]
    (%i3) m1:matrix([a^2+2*a+1=q,b^2+2*b+1=r], [c^2+2*c+1=s,d^2+2*d+1=t])$
    (%i4) format(m1,%equation,%matrix[%noop,%list[%noop,%factor]]);
                       [  2             2           ]
                       [ a  + 2 a + 1  b  + 2 b + 1 ]   [ q  r ]
    (%o4)              [                            ] = [      ]
                       [  2                     2   ]   [ s  t ]
                       [ c  + 2 c + 1    (d + 1)    ]

#### 62.2.2 User defined templates ¶

New templates can be defined by giving the template keyword the property `formatter`; the value should be a function (or lambda expression) of the expression to be formatted and any parameters for the template. For example, `%rectform` and `%if` could be defined as

`put(%rectform,lambda([c],block([r:rectformlist(c)],
format-piece(r[1]) +%I* format-piece(r[2]))),formatter)`

`put(%if, lambda([x,test],
if test(x) then format-piece(x,1)
else
format-piece(x,2)),formatter)`

Functions used for defining templates are the following.

function: %format_piece (piece,nth) ¶

  `lratsubst`’s `eqns` into expression and the result is formatted at the next layer. Format a given piece of an expression, automatically accounting for subtemplates and the remaining template chain. A specific subtemplate, rather than the next one, can be selected by specifying nth.

function: %coerce_bag (op,expr) ¶

  Attempts to coerce expr into an expression with op (one of `=, #, <, <=, >, >=, [` or matrix) as the top-level operator. It coerces the expression by swapping operands between layers but only if adjacent layers are also lists, matrices or relations. This model assumes that a list of equations, for example, can be viewed as an equation whose sides are lists. Certain combinations, particularly those involving inequalities may not be meaningful, however, so some caution is advised.

#### 62.2.3 Determining coefficients ¶

We define the ‘algebras’ of polynomials, trigonometric sums and power series to be those expressions that can be cast into the following forms.

$$ \eqalign{ {\bf P}(v_1,\cdots) &= \{P\,|\, P=\sum_i c_i v^{p_{1,i}}_1 v^{p_{2,i}}_2 \cdots\} \cr {\bf T}(v_1,\cdots) &= \{T\,|\, T=\sum_i [ c_i \cos(m_{1,i} v_1+\cdots)+s_i \sin(m'_{1,i} v_1 +\cdots)] \} \cr {\bf S}(v,O) &= \{S\,|\, S=\sum_i c_i v^{p_i};\,p_n \le O \} } $$

The variables vi may be any atomic expression in the sense of `ratvars`. The shorthands `operator(op)` and `match(predicate)` may be used to specify all subexpressions having op as an operator, or that pass the predicate, respectively.

The coefficients ci and si are general Maxima expressions. In principle they would be independent of the variables vi, but in practice they may contain non-polynomial dependence (or non-trigonometric, in the trigonometric case). These non-polynomial cases would include expressions like `(1 + x)n`, where `n` is symbolic. Likewise, `(xa)b` is, in general, multivalued; unless `a = 1` or `b` is a member of `Z`, or `radexpand=all`, it will not be interpreted as `xab` is a member of P. Furthermore, we extend the algebras to include lists, vectors, matrices and equations, by interpreting a list of polynomials, say, as a polynomial with lists as coefficients.

The exponents pi in series are restricted to numbers, but the exponents cj,i and multiples mj,i for polynomials and trigonometric sums may be general expressions (excluding bags).

The following functions construct a list of the coefficients and ‘keys’, that is, the exponents or multiples. Note that these are sparse representations; no coefficients are zero.

`coeffs(P,v1,...) → [[%poly,v1,...],[c1,p1,1,...],...]`
`trig_coeffs(T,v1,...) →`
`[[%trig,v1,...],[[c1,m1,1,...],...],[[s1,m'1,1,...],...]]`
`series_coeffs(S,v,O) → [[%series,v,O],[c1,p1],...,[cn,pn]`
`Taylor_coeffs(S,v,O) → [[%Taylor,v,O],[c1,p1],...,[cn,pn]`

The latter two functions both expand an expression through order `O`, but the series version only carries expands arithmetic operations and is often considerably faster than `Taylor_coeffs`.

Examples:

    (%i1) load("format")$

    (%i2) cl1:coeffs((a+b*x)*(c-x)^2,x);
                           2          2
    (%o2) [[%poly, x], [a c , 0], [b c  - 2 a c, 1], [a - 2 b c, 2],
                                                              [b, 3]]

    (%i3) map('first,rest(coeffs((a+b*x)*(c-x)^2=q0+q1*x+q2*x^2+q3*x^3,x)));
              2          2
    (%o3) [a c  = q0, b c  - 2 a c = q1, a - 2 b c = q2, b = q3]

    (%i4) trig_coeffs(2*(a+cos(x))*cos(x+3*y),x,y);
    (%o4) [[%trig, x, y], [], [[1, 0, 3], [2 a, 1, 3], [1, 2, 3]]]

    (%i5) series_coeffs((a+b*x)*(c-x)^2,x,2);
                                2          2
    (%o5) [[%series, x, 2], [a c , 0], [b c  - 2 a c, 1],
                                                      [a - 2 b c, 2]]

    (%i6) coeffs((a+b*x)*sin(x),x);
    (%o6)      [[%poly, x], [a sin(x), 0], [b sin(x), 1]]

    (%i7) coeffs((a+log(b)*x)*(c-log(x))^2,operator(log));
                                        2           2
    (%o7) [[%poly, log(x), log(b)], [a c , 0, 0], [c  x, 0, 1],
              [- 2 a c, 1, 0], [- 2 c x, 1, 1], [a, 2, 0], [x, 2, 1]]

#### 62.2.4 Related functions ¶

function: get_coef (clist,k1,...) ¶

  Gets the coefficient from the coefficient list clist corresponding to the keys ki. The keys are matched to variable powers when clist is a `%poly`, `%series` or `%Taylor` form. If clist is a `%trig` then k1 should be `sin` or `cos` and the remaining keys are matched to multipliers.

function: uncoef (clist) ¶

  Reconstructs the expression from a coefficient list clist. The coefficient list can be any of the coefficient list forms.

function: partition_poly (expr,test,v1,...) ¶

  Partitions expr into two polynomials; the first is made of those monomials for which the function test returns true and the second is the remainder. The test function is called on the powers of the vi.

function: partition_trig (expr,sintest,costest,v1,...) ¶

  Trigonometric analog to partition poly; The functions sintest and costest select sine and cosine terms, respectively; each are called on the multipliers of the vi.

function: partition_series (expr,test,v,O) ¶

function: partition_Taylor (expr,test,v,O) ¶

  Analog to `partition_poly` for series.

Example:

    (%i1) load("format")$

    (%i2) partition_poly((a+b*x)*(c-x)^2,'evenp,x);
                          2      2     3       2
    (%o2)   [(a - 2 b c) x  + a c , b x  + (b c  - 2 a c) x]

Support functions

function: matching_parts (expr,predicate,args...) ¶

  Returns a list of all subexpressions of expr for which the application `predicate(piece,args ... )` returns `true`.

function: function_calls (expr,functions...) ¶

  Returns a list of all calls in expr involving any of functions.

function: function_arguments (expr,functions...) ¶

  Returns a list of all argument lists for calls to functions in expr.

Examples:

    (%i1) load("format")$
    (%i2) t2:(a+log(b)*x)*(c-log(x))^2$

    (%i3) matching_parts(t2,constantp);
    (%o3)                       [2, - 1]

    (%i4) function_calls(t2,log);
    (%o4)                   [log(x), log(b)]

#### 62.2.5 Implementation ¶

Original documentation is located in the share/contrib/format directory and contains an appendix describing the implementation algorithm in more detail.