[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

# 7. Simplification

0

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 7.1 Functions and Variables for Simplification

System variable: askexp

  When `asksign` is called, `askexp` is the expression `asksign` is testing.

  At one time, it was possible for a user to inspect `askexp` by entering a Maxima break with control-A.

  ·

  @ref{Category: Declarations and inferences}

Function: askinteger (expr, integer)
Function: askinteger (expr)
Function: askinteger (expr, even)
Function: askinteger (expr, odd)

  `askinteger (expr, integer)` attempts to determine from the `assume` database whether expr is an integer. `askinteger` prompts the user if it cannot tell otherwise, and attempt to install the information in the database if possible. `askinteger (expr)` is equivalent to `askinteger (expr, integer)`.

  `askinteger (expr, even)` and `askinteger (expr, odd)` likewise attempt to determine if expr is an even integer or odd integer, respectively.

  ·

  @ref{Category: Declarations and inferences}

Function: asksign (expr)

  First attempts to determine whether the specified expression is positive, negative, or zero. If it cannot, it asks the user the necessary questions to complete its deduction. The user's answer is recorded in the data base for the duration of the current computation. The return value of `asksign` is one of `pos`, `neg`, or `zero`.

  ·

  @ref{Category: Declarations and inferences}

Function: demoivre (expr)
Option variable: demoivre

  The function `demoivre (expr)` converts one expression without setting the global variable `demoivre`.

  When the variable `demoivre` is `true`, complex exponentials are converted into equivalent expressions in terms of circular functions: `exp (a + b*%i)` simplifies to `%e^a * (cos(b) + %i*sin(b))` if `b` is free of `%i`. `a` and `b` are not expanded.

  The default value of `demoivre` is `false`.

  `exponentialize` converts circular and hyperbolic functions to exponential form. `demoivre` and `exponentialize` cannot both be true at the same time.

  ·

  @ref{Category: Complex variables} · @ref{Category: Trigonometric functions} · @ref{Category: Hyperbolic functions}

Option variable: distribute_over

  Default value: `true`

  `distribute_over` controls the mapping of functions over bags like lists, matrices, and equations. At this time not all Maxima functions have this property. It is possible to look up this property with the command `properties`.

  The mapping of functions is switched off, when setting `distribute_over` to the value `false`.

  Examples:

  The `sin` function maps over a list:

      (%i1) sin([x,1,1.0]);
      (%o1)                 [sin(x), sin(1), .8414709848078965]

  `mod` is a function with two arguments which maps over lists. Mapping over nested lists is possible too:

      (%i2) mod([x,11,2*a],10);
      (%o2)                    [mod(x, 10), 1, 2 mod(a, 5)]
      (%i3) mod([[x,y,z],11,2*a],10);
      (%o3)       [[mod(x, 10), mod(y, 10), mod(z, 10)], 1, 2 mod(a, 5)]

  Mapping of the `floor` function over a matrix and an equation:

      (%i4) floor(matrix([a,b],[c,d]));
                                  [ floor(a)  floor(b) ]
      (%o4)                       [                    ]
                                  [ floor(c)  floor(d) ]
      (%i5) floor(a=b);
      (%o5)                         floor(a) = floor(b)

  Functions with more than one argument map over any of the arguments or all arguments:

      (%i6) expintegral_e([1,2],[x,y]);
      (%o6) [[expintegral_e(1, x), expintegral_e(1, y)],
             [expintegral_e(2, x), expintegral_e(2, y)]]

  Check if a function has the property distribute_over:

      (%i7) properties(abs);
      (%o7) [integral, distributes over bags, noun, rule, gradef]

  ·

  @ref{Category: Simplification flags and variables}

Option variable: domain

  Default value: `real`

  When `domain` is set to `complex`, `sqrt (x^2)` will remain `sqrt (x^2)` instead of returning `abs(x)`.

  ·

  @ref{Category: Simplification flags and variables}

Function: expand (expr)
Function: expand (expr, p, n)

  Expand expression expr. Products of sums and exponentiated sums are multiplied out, numerators of rational expressions which are sums are split into their respective terms, and multiplication (commutative and non-commutative) are distributed over addition at all levels of expr.

  For polynomials one should usually use `ratexpand` which uses a more efficient algorithm.

  `maxnegex` and `maxposex` control the maximum negative and positive exponents, respectively, which will expand.

  `expand (expr, p, n)` expands expr, using p for `maxposex` and n for `maxnegex`. This is useful in order to expand part but not all of an expression.

  `expon` - the exponent of the largest negative power which is automatically expanded (independent of calls to `expand`). For example if `expon` is 4 then `(x+1)^(-5)` will not be automatically expanded.

  `expop` - the highest positive exponent which is automatically expanded. Thus `(x+1)^3`, when typed, will be automatically expanded only if `expop` is greater than or equal to 3. If it is desired to have `(x+1)^n` expanded where `n` is greater than `expop` then executing `expand ((x+1)^n)` will work only if `maxposex` is not less than `n`.

  `expand(expr, 0, 0)` causes a resimplification of `expr`. `expr` is not reevaluated. In distinction from `ev(expr, noeval)` a special representation (e. g. a CRE form) is removed. See also `ev`.

  The `expand` flag used with `ev` causes expansion.

  The file ``simplification/facexp.mac'` contains several related functions (in particular `facsum`, `factorfacsum` and `collectterms`, which are autoloaded) and variables (`nextlayerfactor` and `facsum_combine`) that provide the user with the ability to structure expressions by controlled expansion. Brief function descriptions are available in ``simplification/facexp.usg'`. A demo is available by doing `demo("facexp")`.

  Examples:

      (%i1) expr:(x+1)^2*(y+1)^3;
                                            2        3
      (%o1)                          (x + 1)  (y + 1)
      (%i2) expand(expr);
             2  3        3    3      2  2        2      2      2
      (%o2) x  y  + 2 x y  + y  + 3 x  y  + 6 x y  + 3 y  + 3 x  y
                                                       2
                                      + 6 x y + 3 y + x  + 2 x + 1

      (%i3) expand(expr,2);
                            2        3              3          3
      (%o3)                x  (y + 1)  + 2 x (y + 1)  + (y + 1)

      (%i4) expr:(x+1)^-2*(y+1)^3;
                                                3
                                         (y + 1)
      (%o4)                              --------
                                                2
                                         (x + 1)
      (%i5) expand(expr);
                       3               2
                      y             3 y            3 y             1
      (%o5)      ------------ + ------------ + ------------ + ------------
                  2              2              2              2
                 x  + 2 x + 1   x  + 2 x + 1   x  + 2 x + 1   x  + 2 x + 1

      (%i6) expand(expr,2,2);
                                                3
                                         (y + 1)
      (%o6)                            ------------
                                        2
                                       x  + 2 x + 1

  Resimplify an expression without expansion:

      (%i7) expr:(1+x)^2*sin(x);
                                             2
      (%o7)                           (x + 1)  sin(x)
      (%i8) exponentialize:true;
      (%o8)                                true
      (%i9) expand(expr,0,0);
                                         2    %i x     - %i x
                               %i (x + 1)  (%e     - %e      )
      (%o9)                  - -------------------------------
                                              2

  ·

  @ref{Category: Expressions}

Function: expandwrt (expr, x_1, ..., x_n)

  Expands expression `expr` with respect to the variables x_1, ..., x_n. All products involving the variables appear explicitly. The form returned will be free of products of sums of expressions that are not free of the variables. x_1, ..., x_n may be variables, operators, or expressions.

  By default, denominators are not expanded, but this can be controlled by means of the switch `expandwrt_denom`.

  This function is autoloaded from ``simplification/stopex.mac'`.

  ·

  @ref{Category: Expressions}

Option variable: expandwrt_denom

  Default value: `false`

  `expandwrt_denom` controls the treatment of rational expressions by `expandwrt`. If `true`, then both the numerator and denominator of the expression will be expanded according to the arguments of `expandwrt`, but if `expandwrt_denom` is `false`, then only the numerator will be expanded in that way.

  ·

  @ref{Category: Expressions}

Function: expandwrt_factored (expr, x_1, ..., x_n)

  is similar to `expandwrt`, but treats expressions that are products somewhat differently. `expandwrt_factored` expands only on those factors of `expr` that contain the variables x_1, ..., x_n.

  This function is autoloaded from ``simplification/stopex.mac'`.

  ·

  @ref{Category: Expressions}

Option variable: expon

  Default value: 0

  `expon` is the exponent of the largest negative power which is automatically expanded (independent of calls to `expand`). For example, if `expon` is 4 then `(x+1)^(-5)` will not be automatically expanded.

  ·

  @ref{Category: Expressions}

Function: exponentialize (expr)
Option variable: exponentialize

  The function `exponentialize (expr)` converts circular and hyperbolic functions in expr to exponentials, without setting the global variable `exponentialize`.

  When the variable `exponentialize` is `true`, all circular and hyperbolic functions are converted to exponential form. The default value is `false`.

  `demoivre` converts complex exponentials into circular functions. `exponentialize` and `demoivre` cannot both be true at the same time.

  ·

  @ref{Category: Complex variables} · @ref{Category: Trigonometric functions} · @ref{Category: Hyperbolic functions}

Option variable: expop

  Default value: 0

  `expop` is the highest positive exponent which is automatically expanded. Thus `(x + 1)^3`, when typed, will be automatically expanded only if `expop` is greater than or equal to 3. If it is desired to have `(x + 1)^n` expanded where `n` is greater than `expop` then executing `expand ((x + 1)^n)` will work only if `maxposex` is not less than n.

  ·

  @ref{Category: Expressions}

Option variable: factlim

  Default value: -1

  `factlim` specifies the highest factorial which is automatically expanded. If it is -1 then all integers are expanded.

  ·

  @ref{Category: Gamma and factorial functions}

Function: intosum (expr)

  Moves multiplicative factors outside a summation to inside. If the index is used in the outside expression, then the function tries to find a reasonable index, the same as it does for `sumcontract`. This is essentially the reverse idea of the `outative` property of summations, but note that it does not remove this property, it only bypasses it.

  In some cases, a `scanmap (multthru, expr)` may be necessary before the `intosum`.

  ·

  @ref{Category: Expressions}

Declaration: lassociative

  `declare (g, lassociative)` tells the Maxima simplifier that `g` is left-associative. E.g., `g (g (a, b), g (c, d))` will simplify to `g (g (g (a, b), c), d)`.

  ·

  @ref{Category: Declarations and inferences} · @ref{Category: Operators} · @ref{Category: Simplification}

Declaration: linear

  One of Maxima's operator properties. For univariate `f` so declared, "expansion" `f(x + y)` yields `f(x) + f(y)`, `f(a*x)` yields `a*f(x)` takes place where `a` is a "constant". For functions of two or more arguments, "linearity" is defined to be as in the case of `sum` or `integrate`, i.e., `f (a*x + b, x)` yields `a*f(x,x) + b*f(1,x)` for `a` and `b` free of `x`.

  `linear` is equivalent to `additive` and `outative`. See also `opproperties`.

  ·

  @ref{Category: Declarations and inferences} · @ref{Category: Operators} · @ref{Category: Simplification}

Declaration: mainvar

  You may declare variables to be `mainvar`. The ordering scale for atoms is essentially: numbers < constants (e.g., `%e`, `%pi`) < scalars < other variables < mainvars. E.g., compare `expand ((X+Y)^4)` with `(declare (x, mainvar), expand ((x+y)^4))`. (Note: Care should be taken if you elect to use the above feature. E.g., if you subtract an expression in which `x` is a `mainvar` from one in which `x` isn't a `mainvar`, resimplification e.g. with `ev (expr, simp)` may be necessary if cancellation is to occur. Also, if you save an expression in which `x` is a `mainvar`, you probably should also save `x`.)

  ·

  @ref{Category: Declarations and inferences} · @ref{Category: Expressions}

Option variable: maxapplydepth

  Default value: 10000

  `maxapplydepth` is the maximum depth to which `apply1` and `apply2` will delve.

  ·

  @ref{Category: Function application}

Option variable: maxapplyheight

  Default value: 10000

  `maxapplyheight` is the maximum height to which `applyb1` will reach before giving up.

  ·

  @ref{Category: Function application}

Option variable: maxnegex

  Default value: 1000

  `maxnegex` is the largest negative exponent which will be expanded by the `expand` command (see also `maxposex`).

  ·

  @ref{Category: Expressions}

Option variable: maxposex

  Default value: 1000

  `maxposex` is the largest exponent which will be expanded with the `expand` command (see also `maxnegex`).

  ·

  @ref{Category: Expressions}

Declaration: multiplicative

  `declare (f, multiplicative)` tells the Maxima simplifier that `f` is multiplicative.

  1. If `f` is univariate, whenever the simplifier encounters `f` applied to a product, `f` distributes over that product. E.g., `f(x*y)` simplifies to `f(x)*f(y)`.
  2. If `f` is a function of 2 or more arguments, multiplicativity is defined as multiplicativity in the first argument to `f`, e.g., `f (g(x) * h(x), x)` simplifies to `f (g(x) ,x) * f (h(x), x)`.

  This simplification does not occur when `f` is applied to expressions of the form `product (x[i], i, m, n)`.

  ·

  @ref{Category: Declarations and inferences} · @ref{Category: Expressions} · @ref{Category: Simplification}

Option variable: negdistrib

  Default value: `true`

  When `negdistrib` is `true`, -1 distributes over an expression. E.g., `-(x + y)` becomes `- y - x`. Setting it to `false` will allow `- (x + y)` to be displayed like that. This is sometimes useful but be very careful: like the `simp` flag, this is one flag you do not want to set to `false` as a matter of course or necessarily for other than local use in your Maxima.

  ·

  @ref{Category: Simplification flags and variables}

Option variable: negsumdispflag

  Default value: `true`

  When `negsumdispflag` is `true`, `x - y` displays as `x - y` instead of as `- y + x`. Setting it to `false` causes the special check in display for the difference of two expressions to not be done. One application is that thus `a + %i*b` and `a - %i*b` may both be displayed the same way.

  ·

  @ref{Category: Display flags and variables}

Special symbol: noeval

  `noeval` suppresses the evaluation phase of `ev`. This is useful in conjunction with other switches and in causing expressions to be resimplified without being reevaluated.

  ·

  @ref{Category: Evaluation flags}

Declaration: noun

  `noun` is one of the options of the `declare` command. It makes a function so declared a "noun", meaning that it won't be evaluated automatically.

  ·

  @ref{Category: Nouns and verbs}

Option variable: noundisp

  Default value: `false`

  When `noundisp` is `true`, nouns display with a single quote. This switch is always `true` when displaying function definitions.

  ·

  @ref{Category: Display flags and variables} · @ref{Category: Nouns and verbs}

Special symbol: nouns

  `nouns` is an `evflag`. When used as an option to the `ev` command, `nouns` converts all "noun" forms occurring in the expression being `ev`'d to "verbs", i.e., evaluates them. See also `noun`, `nounify`, `verb`, and `verbify`.

  ·

  @ref{Category: Evaluation flags} · @ref{Category: Nouns and verbs}

Option variable: numer

  `numer` causes some mathematical functions (including exponentiation) with numerical arguments to be evaluated in floating point. It causes variables in `expr` which have been given numerals to be replaced by their values. It also sets the `float` switch on.

  See also `%enumer`.

  Examples:

      (%i1) [sqrt(2), sin(1), 1/(1+sqrt(3))];
                                                     1
      (%o1)                   [sqrt(2), sin(1), -----------]
                                                sqrt(3) + 1
      (%i2) [sqrt(2), sin(1), 1/(1+sqrt(3))],numer;
      (%o2)      [1.414213562373095, .8414709848078965, .3660254037844387]

  ·

  @ref{Category: Numerical evaluation} · @ref{Category: Evaluation flags}

Function: numerval (x_1, expr_1, ..., var_n, expr_n)

  Declares the variables `x_1`, ..., x_n to have numeric values equal to `expr_1`, ..., `expr_n`. The numeric value is evaluated and substituted for the variable in any expressions in which the variable occurs if the `numer` flag is `true`. See also `ev`.

  The expressions `expr_1`, ..., `expr_n` can be any expressions, not necessarily numeric.

  ·

  @ref{Category: Declarations and inferences} · @ref{Category: Numerical evaluation}

System variable: opproperties

  `opproperties` is the list of the special operator properties recognized by the Maxima simplifier: `linear`, `additive`, `multiplicative`, `outative`, `evenfun`, `oddfun`, `commutative`, `symmetric`, `antisymmetric`, `nary`, `lassociative`, `rassociative`.

  ·

  @ref{Category: Global variables} · @ref{Category: Operators}

Option variable: opsubst

  Default value: `true`

  When `opsubst` is `false`, `subst` does not attempt to substitute into the operator of an expression. E.g., `(opsubst: false, subst (x^2, r, r+r[0]))` will work.

  ·

  @ref{Category: Expressions}

Declaration: outative

  `declare (f, outative)` tells the Maxima simplifier that constant factors in the argument of `f` can be pulled out.

  1. If `f` is univariate, whenever the simplifier encounters `f` applied to a product, that product will be partitioned into factors that are constant and factors that are not and the constant factors will be pulled out. E.g., `f(a*x)` will simplify to `a*f(x)` where `a` is a constant. Non-atomic constant factors will not be pulled out.
  2. If `f` is a function of 2 or more arguments, outativity is defined as in the case of `sum` or `integrate`, i.e., `f (a*g(x), x)` will simplify to `a * f(g(x), x)` for `a` free of `x`.

  `sum`, `integrate`, and `limit` are all `outative`.

  ·

  @ref{Category: Declarations and inferences} · @ref{Category: Operators}

Declaration: posfun

  `declare (f, posfun)` declares `f` to be a positive function. `is (f(x) > 0)` yields `true`.

  ·

  @ref{Category: Declarations and inferences} · @ref{Category: Operators}

Special symbol: pred

  As an argument in a call to `ev (expr)`, `pred` causes predicates (expressions which evaluate to `true` or `false`) to be evaluated. See `ev`.

  Example:

      (%i1) 1<2;
      (%o1)                                1 < 2
      (%i2) 1<2,pred;
      (%o2)                                true

  ·

  @ref{Category: Evaluation flags}

Function: radcan (expr)

  Simplifies expr, which can contain logs, exponentials, and radicals, by converting it into a form which is canonical over a large class of expressions and a given ordering of variables; that is, all functionally equivalent forms are mapped into a unique form. For a somewhat larger class of expressions, `radcan` produces a regular form. Two equivalent expressions in this class do not necessarily have the same appearance, but their difference can be simplified by `radcan` to zero.

  For some expressions `radcan` is quite time consuming. This is the cost of exploring certain relationships among the components of the expression for simplifications based on factoring and partial-fraction expansions of exponents.

  Examples:

      (%i1) radcan((log(x+x^2)-log(x))^a/log(1+x)^(a/2));
                                                 a/2
      (%o1)                            log(x + 1)

      (%i2) radcan((log(1+2*a^x+a^(2*x))/log(1+a^x)));
      (%o2)                                  2

      (%i3) radcan((%e^x-1)/(1+%e^(x/2)));
                                           x/2
      (%o3)                              %e    - 1

  ·

  @ref{Category: Simplification functions}

Option variable: radexpand

  Default value: `true`

  `radexpand` controls some simplifications of radicals.

  When `radexpand` is `all`, causes nth roots of factors of a product which are powers of n to be pulled outside of the radical. E.g. if `radexpand` is `all`, `sqrt (16*x^2)` simplifies to `4*x`.

  More particularly, consider `sqrt (x^2)`.

  - If `radexpand` is `all` or `assume (x > 0)` has been executed, `sqrt(x^2)` simplifies to `x`.
  - If `radexpand` is `true` and `domain` is `real` (its default), `sqrt(x^2)` simplifies to `abs(x)`.
  - If `radexpand` is `false`, or `radexpand` is `true` and `domain` is `complex`, `sqrt(x^2)` is not simplified.

  Note that `domain` only matters when `radexpand` is `true`.

  ·

  @ref{Category: Simplification flags and variables}

Option variable: radsubstflag

  Default value: `false`

  `radsubstflag`, if `true`, permits `ratsubst` to make substitutions such as `u` for `sqrt (x)` in `x`.

  ·

  @ref{Category: Simplification flags and variables}

Declaration: rassociative

  `declare (g, rassociative)` tells the Maxima simplifier that `g` is right-associative. E.g., `g(g(a, b), g(c, d))` simplifies to `g(a, g(b, g(c, d)))`.

  ·

  @ref{Category: Declarations and inferences} · @ref{Category: Operators}

Function: scsimp (expr, rule_1, ..., rule_n)

  Sequential Comparative Simplification (method due to Stoute). `scsimp` attempts to simplify expr according to the rules rule_1, ..., rule_n. If a smaller expression is obtained, the process repeats. Otherwise after all simplifications are tried, it returns the original answer.

  `example (scsimp)` displays some examples.

  ·

  @ref{Category: Simplification functions}

Option variable: simp

  Default value: `true`

  `simp` enables simplification. This is the standard. `simp` is also an `evflag`, which is recognized by the function `ev`. See `ev`.

  When `simp` is used as an `evflag` with a value `false`, the simplification is suppressed only during the evaluation phase of an expression. The flag can not suppress the simplification which follows the evaluation phase.

  Examples:

  The simplification is switched off globally. The expression `sin(1.0)` is not simplified to its numerical value. The `simp`-flag switches the simplification on.

      (%i1) simp:false;
      (%o1)                                false
      (%i2) sin(1.0);
      (%o2)                              sin(1.0)
      (%i3) sin(1.0),simp;
      (%o3)                          .8414709848078965

  The simplification is switched on again. The `simp`-flag cannot suppress the simplification completely. The output shows a simplified expression, but the variable `x` has an unsimplified expression as a value, because the assignment has occurred during the evaluation phase of the expression.

      (%i4) simp:true;
      (%o4)                                true
      (%i5) x:sin(1.0),simp:false;
      (%o5)                          .8414709848078965
      (%i6) :lisp $X
      ((%SIN) 1.0)

  ·

  @ref{Category: Evaluation flags}

Option variable: simpsum

  Default value: `false`

  When `simpsum` is `true`, the result of a `sum` is simplified. This simplification may sometimes be able to produce a closed form. If `simpsum` is `false` or if the quoted form `'sum` is used, the value is a sum noun form which is a representation of the sigma notation used in mathematics.

  ·

  @ref{Category: Sums and products} · @ref{Category: Simplification flags and variables}

Function: sumcontract (expr)

  Combines all sums of an addition that have upper and lower bounds that differ by constants. The result is an expression containing one summation for each set of such summations added to all appropriate extra terms that had to be extracted to form this sum. `sumcontract` combines all compatible sums and uses one of the indices from one of the sums if it can, and then try to form a reasonable index if it cannot use any supplied.

  It may be necessary to do an `intosum (expr)` before the `sumcontract`.

  ·

  @ref{Category: Sums and products}

Option variable: sumexpand

  Default value: `false`

  When `sumexpand` is `true`, products of sums and exponentiated sums simplify to nested sums.

  See also `cauchysum`.

  Examples:

      (%i1) sumexpand: true$
      (%i2) sum (f (i), i, 0, m) * sum (g (j), j, 0, n);
                           m      n
                          ====   ====
                          \      \
      (%o2)                >      >     f(i1) g(i2)
                          /      /
                          ====   ====
                          i1 = 0 i2 = 0
      (%i3) sum (f (i), i, 0, m)^2;
                           m      m
                          ====   ====
                          \      \
      (%o3)                >      >     f(i3) f(i4)
                          /      /
                          ====   ====
                          i3 = 0 i4 = 0

  ·

  @ref{Category: Sums and products} · @ref{Category: Simplification flags and variables}

Option variable: sumsplitfact

  Default value: `true`

  When `sumsplitfact` is `false`, `minfactorial` is applied after a `factcomb`.

  ·

  @ref{Category: Gamma and factorial functions} · @ref{Category: Simplification flags and variables}

Declaration: symmetric

  `declare (h, symmetric)` tells the Maxima simplifier that `h` is a symmetric function. E.g., `h (x, z, y)` simplifies to `h (x, y, z)`.

  `commutative` is synonymous with `symmetric`.

  ·

  @ref{Category: Declarations and inferences} · @ref{Category: Operators}

Function: unknown (expr)

  Returns `true` if and only if expr contains an operator or function not recognized by the Maxima simplifier.

  ·

  @ref{Category: Predicate functions} · @ref{Category: Simplification functions}

0

[ << ] | [ >> ] |  |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

This document was generated by Charlie & on January, 31 2011 using texi2html 1.76.