summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/latex/polexpr/polexpr.txt
blob: 19d5ccdf9c991e5bc7ad23aa21bee0026faa3846 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
.. comment: -*- fill-column: 72; mode: rst; -*-

Package polexpr documentation
=============================

First Examples
--------------

The syntax is::

    \poldef <name>(x):=<expression in variable x>;

where in place of ``x`` an arbitrary *dummy variable* is authorized
(i.e. per default any of ``[a..z|A..Z]``; more letters can be declared
under Unicode engines.) One can also issue::

    \PolDef{name}{expression in variable x}

which admits an optional first argument to modify the variable letter
from its default ``x``.

``\poldef f(x):= 1-x+x^2;``
    defines polynomial ``f``. Polynomial names must start with a letter
    and may contain letters, digits, and underscores. The variable must
    be a single letter. The colon character is optional. The semi-colon
    at end of expression is mandatory.

``\PolDef{f}{1-x+x^2}``
    does the same as ``\poldef f(x):= 1-x+x^2;`` To use another letter
    than ``x`` in the expression, one must pass it as an extra optional
    argument to ``\PolDef``. Useful if the semi-colon has been assigned
    some non-standard catcode by some package.

``\PolLet{g}{f}``
    saves a copy of ``f`` under name ``g``.
    
``\poldef f(z):= f(z)^2;``
    redefines ``f`` in terms of itself.

``\poldef f(T):= f(f(T));``
    again redefines ``f`` in terms of its (new) self.

``\poldef k(z):= f(z)-g(g(z)^2)^2;``
    should now define the zero polynomial... Let's check:
    ``\[ k(z) = \PolTypeset[z]{k} \]``

``\PolDiff{f}{df_dx}``
    sets ``df_dx`` to the derivative of ``f``.
    
``\PolDiff{df_dx}{f_xx}``
    obtains second derivative.

``\PolDiff[3]{f}{d3f_dx3}``
    computes directly the third derivative. Its name does not have to be
    chosen so complicated ``:)``, but the right quote ``'`` is not
    allowed in polynomial names (currently).

::

  $f(z)   = \PolTypeset[z]{f}    $\newline
  $f'(z)  = \PolTypeset[z]{df_dx}$\newline
  $f''(z) = \PolTypeset[z]{f_xx}$\newline
  $f'''(z)= \PolTypeset[z]{d3f_dx3}$\par

.. important:: 

   The package does not currently know rational functions: ``/`` in
   a parsed polynomial expression does the Euclidean quotient::

     (1-x^2)/(1-x)

   does give ``1+x`` but ::

     (1/(1-x))*(1-x^2)

   evaluates to zero. This will work as expected::

     \poldef k(x):= (x-1)(x-2)(x-3)(x-4)/(x^2-5x+4);

.. attention:: 

   ``1/2 x`` skips the space and is treated like ``1/(2x)`` because of
   the tacit multiplication rules of \xintexpr. But this means it gives
   zero! Thus one must use ``(1/2)x`` or ``1/2*x`` or ``(1/2)*x`` for
   disambiguation: ``x-1/2*x^2+1/3*x^3...``

After::

  \poldef f1(x):= 25(x-1)(x^2-2)(x-3)(x-4)(x-5);%
  \poldef f2(x):= 37(x-1)(x^2-2)(x-6)(x-7)(x-8);%

the macro call ``\PolGCD{f1}{f2}{k}`` sets ``k`` to the (unitary) GCD of
``f1`` and ``f2``.

``\PolToExpr{k}``
    will thus (expandably) give in this case ``2-2*x^1-1*x^2+1*x^3``.
    This is useful for console or file output (the syntax is Maple- and
    PSTricks-compatible; currently the letter ``x`` in output is not
    customizable, but this can easily be added if requested from author.)

Non-expandable macros
---------------------

``\poldef name(letter):= polynomial expression using letter;``
    This evaluates the polynomial expression and stores the coefficients
    in a private structure accessible later via other package macros,
    under the user-chosen ``name``. Of course previously defined
    polynomials are allowed in a new expression. Names must start with a
    letter and are constituted of letters, digits and underscore
    characters. See Examples above.

    As a side effect the function ``name()`` is recognized as a genuine
    ``\xintexpr...\relax`` function for (exact) numerical evaluation. It
    computes values not according to the original expression but via
    the Horner scheme corresponding to the polynomial coefficients.

    The original expression is lost after parsing, and in particular
    the package provides no way to typeset it. This has to be done
    manually, if needed.

``\PolDef{name}{P(x)}``
    Does the same but the variable is assumed to be ``x``. To use
    another letter, pass it as first optional argument:
    ``\PolDef[X]{name}{P(X)}``.

``\PolLet{g}{f}``
    Makes a copy of already defined polynomial f to new one g. Same
    effect as ``\PolDef{g}{f(x)}`` but faster.

``\PolAssign{f}\toarray\Array``
    Defines a one-argument expandable macro ``\Array{#1}`` which expands
    to the (raw) #1th polynomial coefficient.

    - Attention, coefficients here are indexed starting at 1.

    - With #1=-1, -2, ..., ``\Array{#1}`` returns leading coefficients.

    - With #1=0, returns the number of coefficients, i.e. ``1 + deg f``
      for non-zero polynomials.

    - Out-of-range #1's return ``0/1[0]``.

``\PolGet{f}\fromarray\Array``
    Does the converse operation to ``\PolAssign{f}\toarray\Array``. No
    error checks on validity of coefficients as numbers. Each
    ``\Array{index}`` is expanded in an ``\edef`` before being assigned
    to a coefficient. Leading zero coefficients are removed from the
    polynomial.

    (contrived) Example::

      \xintAssignArray{1}{-2}{5}{-3}\to\foo
      \PolGet{f}\fromarray\foo

    This will define ``f`` as would have ``\poldef f(x):=1-2x+5x^2-3x^3;``.
    However the coefficients are still in their original form (i.e.
    they were not subjected to ``\xintRaw`` or similar xintfrac macro.)

``\PolFromCSV{f}{comma separated coefficients}``
    Defines a polynomial directly from the comma separated list (or a
    macro expanding to such a list) of its coefficients, the constant
    term being the first item. No validity checks. Spaces from the list
    argument are trimmed. List items are expanded in an ``\edef``, but
    currently left in their original form like e.g. ``1.5e3`` which is
    not converted to ``15/1[2]`` *raw* xintfrac format (this may
    change).

    Leading zero coefficients are removed::

      \PolFromCSV{J}{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

    defines the zero polynomial, which has only one (zero) coefficient.

    See also expandable macro ``\PolToCSV``.

``\PolTypeset{name}``
    Typesets in descending powers in math mode. It uses letter ``x`` but
    this can be changed via an optional argument::

      \PolTypeset[z]{name}

    By default zero coefficients are skipped (issue ``\poltypesetalltrue``
    to get all of them in output).

    Macros ``\PolTypesetCmd``, ``\PolTypesetPlus``, ``\PolTypesetMonomial``
    can help configure the output. See the package code.

``\PolTypeset*{name}``
    Typesets in ascending powers. Change the letter from its default
    ``x`` by optional argument.

``\PolDiff{f1}{f2}``
    This sets f2 to the first derivative of ``f1``. It is allowed to
    issue ``\PolDiff{f}{f}``, effectively replacing ``f`` by ``f'``.

    Coefficients of the result ``f2`` are irreducible fractions
    (see `Technicalities`_ for the whole story.)

``\PolDiff[N]{f1}{f2}``
    This sets ``f2`` to the ``N``-th derivative of ``f1``. Identical
    arguments is allowed. With ``N=0``, same effect as
    ``\PolLet{f2}{f1}``. With negative ``N``, switches to using
    ``\PolAntiDiff``.

``\PolAntiDiff{f1}{f2}``
    This sets ``f2`` to the primitive of ``f1`` vanishing at zero.

    Coefficients of the result ``f2`` are irreducible fractions
    (see `Technicalities`_ for the whole story.)

``\PolAntiDiff[N]{f1}{f2}``
    This sets ``f2`` to the result of ``N`` successive integrations on
    ``f1``. With negative ``N``, it switches to using ``\PolDiff``.

``\PolDivide{f1}{f2}{Q}{R}``
    This sets ``Q`` and ``R`` to be the quotient and remainder in the
    Euclidean division of ``f1`` by ``f2``.

``\PolGCD{f}{g}{k}``
    This sets ``k`` to be the G.C.D. It is a unitary polynomial except
    if both ``f`` and ``g`` vanish, then ``k`` is the zero polynomial.

``\PolMapCoeffs{\macro}{name}``
    It modifies each coefficient of the defined polynomial via the
    *expandable* macro ``\macro``. The degree is adjusted as necessary
    if some leading coefficients vanish after the operation. In
    replacement text of ``\macro``, ``\index`` expands to the
    coefficient index (which is defined to be zero for the constant
    term).

    Notice that ``\macro`` will have to handle inputs of the shape
    ``A/B[N]`` (xintfrac internal notation). This means that it probably
    will have to be expressed in terms of macros from xintfrac package.

    Example::

      \def\foo#1{\xintMul{#1}{\the\numexpr\index*\index\relax}}

    (or with ``\xintSqr{\xindex}``) to replace ``n``-th coefficient
    ``f_n`` by ``f_n*n^2``.

``\PolReduceCoeffs{name}``
    About the same as ``\PolMapCoeffs{\xintIrr}{name}`` (but adds
    ``[0]`` postfix which speeds up xintfrac operations when
    evaluating.)

Expandable macros
-----------------

All these macros expand completely in two steps except ``\PolToExpr``
which needs a ``\write``, ``\edef`` or a ``\csname...\endcsname`` context.

``\PolEval{name}\At{value}``
    It boils down to ``\xinttheexpr reduce(name(value))\relax``.

``\PolNthCoeff{name}{N}``
    It expands to the raw ``N``-th coefficient (``0/1[0]`` if index is
    out of range). With ``N=-1``, ``-2``, ... expands to the leading
    coefficients.

``\PolDegree{name}``
    It expands to the degree. This is ``-1`` if zero polynomial but this
    may change in future. Should it then expand to ``-\infty`` ?

``\PolToExpr{f}``
    Expands to ``f_0 + f_1*x + f_2*x^2 + ...`` (ascending powers). [1]_,
    [2]_

    .. [1] in a ``\write``, ``\edef``, or ``\csname...\endcsname``, but
           not under ``\romannumeral-`0``.

    .. [2] the letter ``x`` is (in this release) not customizable.

    By default zero coefficients are skipped (issue ``\poltoexprtrue`` to
    get all of them in output).

    No ``+`` sign before negative coefficients, for compliance with Maple
    input format. This means though that parsing the result back via
    naive delimited macros is difficult, see ``\PolToList`` and ``\PolToCSV``
    for more low-level formats making it easier to get expandably some
    output of one's choice, which may possibly be parsed later on by
    other macros of one's design, or from other packages.

    Of course ``\PolToExpr{f}`` can be inserted in a \poldef, as the
    latter expands token by token, hence will force complete expansion
    of ``\PolToExpr{f}``, but simply ``f(x)`` will be more efficient for the
    identical result.

    ``\PolToExprCmd`` is the one-argument macro used by ``\PolToExpr`` for the
    coefficients, it defaults to ``\xintPRaw{\xintRawWithZeros{#1}}``. One
    will have to redefine it to use ``\xintIrr{#1}`` in place of
    ``\xintRawWithZeros{#1}`` to get in output reduced coefficients.

``\PolToList{f}``
    Expands to ``{f_0}{f_1}...{f_N}`` with ``N`` = degree of f (except
    zero polynomial which does give ``{0/1[0]}`` and not an empty
    output.)

``\PolToCSV{f}``
    Expands to ``f_0, f_1, f_2, ....., f_N``. Converse to
    ``\PolFromCSV``.

Technicalities
--------------

- The catcode of the semi-colon is reset temporarily by ``\poldef`` macro in
  case some other package (for example the French babel module) may have
  made it active. This will fail though if the whole thing was already
  part of a macro argument, in such cases one can use ``\PolDef`` rather.
  The colon in ``:=`` may be active with no consequences.

- Beware the ``1/2 x`` problem: as mentioned above, it will be give zero due
  to the tacit multiplication rules of ``\xintexpr`` and to the fact that
  the package will do the Euclidean division of ``1`` by polynomial ``2x``.

- During execution of polynomial operations by ``\poldef`` (but not
  during the initial purely numerical parsing of the expression), the
  xintfrac macro ``\xintAdd`` is temporarily patched to always express
  ``a/b + c/d`` with ``l.c.m.(b,d)`` as denominator. Indeed the current
  (xint 1.2p) ``\xintAdd`` uses ``(ad+bc)/bd`` formula except if ``b``
  divides ``d`` or ``d`` divides ``b``, which quickly leads in real life
  to big denominators.

  It is probable that this convention will be backported as default
  behaviour of xintfrac's ``\xintAdd`` in a future xint release. When this
  change is merged, there will be an impact on coefficients computed by
  ``\poldef`` because the change will apply even to the pure numerical
  evaluations arising during the initial stage of the parsing. Of course
  the coefficients are still the same rational numbers, only
  representation as fractions may change.

- As a consequence of previous rule, user-chosen common denominators
  survive addition and multiplications::

    \poldef P(x):= 1/2 + 2/2*x + 3/2*x^3 + 4/2*x^4;
    \poldef Q(x):= 1/3 + (2/3)x + (3/3)x^3 + (4/3)x^4;
    \poldef PQ(x):= P(x)Q(x);

  gives the polynomial::

    1/6+4/6*x^1+4/6*x^2+6/6*x^3+20/6*x^4+16/6*x^5+9/6*x^6+24/6*x^7+16/6*x^8

  where all coefficients have the same denominator 6 (which in this
  example is the ``l.c.m`` of the denominators of the reduced coefficients.)

- ``\PolDiff`` always applies ``\xintIrr`` to the resulting coefficients, except
  that the *power of ten* part ``[N]`` (for example an input in scientific
  notation such as ``1.23e5`` gives ``123/1[3]`` internally in xintfrac) is not
  taken into account in the reduction of the fraction. This is tentative
  and may change.

  Same remark for ``\PolAntiDiff``.

- If ``f`` was created from comma separated values by macro \PolFromCSV,
  then the coefficients will be in the output of ``\PolToList`` and
  ``\PolToCSV`` in the same format as originally in input: a ``1.3e2``
  will again be a ``1.3e2``.
  
  In contrast when such coefficients are used in a ``\poldef`` (or
  ``\PolDef``) expression, they get transformed during the parsing to
  the xintfrac *raw* format. This is an unavoidable consequence of usage
  by \poldef of ``\xintdeffunc`` which itself is based on ``\xintexpr.``
  This *raw* format speeds up expansion of xintfrac macros for numerical
  evaluations.

- Currently, the package does not as a result of ``\poldef`` add to the TeX
  memory an already pre-computed *array* structure for the polynomial
  coefficients, as would be constructed by ``\PolAssign{f}\toarray\macro``.
  Such structures are used, but for internal calculations in temporarily
  restricted scopes. Apart from the function ``f()`` known to the
  (numerical) ``\xintexpr`` parser (whose meaning can be found in the log
  file after \xintverbosetrue), the data is (currently) stored in a
  single other macro encapsulating the degree, and the coefficients as a
  list. This may evolve in future.

- As is to be expected internal structures of the package are barely
  documented and unstable. Don't use them.

RELEASES
--------

- 0.1 (2018/01/11): initial release (files README, polexpr.sty).
- 0.2 (2018/01/14): documentation moved to polexpr.{txt,html}.

Files of 0.2 release:

- README.md,
- polexpr.sty (package file),
- polexpr.txt (documentation),
- polexpr.html (conversion via `DocUtils`__ rst2html.py)

  __  http://docutils.sourceforge.net/docs/index.html

See README.md for the License and the change log.