This is maxima.info, produced by makeinfo version 5.1 from maxima.texi.


File: maxima.info,  Node: Gleichungen,  Next: Lineare Algebra,  Prev: Polynome,  Up: Top

18 Gleichungen
**************

* Menu:

* Funktionen und Variablen für Gleichungen::


File: maxima.info,  Node: Funktionen und Variablen für Gleichungen,  Prev: Gleichungen,  Up: Gleichungen

18.1 Funktionen und Variablen für Gleichungen
=============================================

 -- Optionsvariable: %rnum
     Standardwert: '0'

     Wenn notwendig erzeugen die Funktionen 'solve' und 'algsys' freie
     Parameter, die in die Lösungen eingesetzt werden.  Die Parameter
     haben den Namen '%r<<num>>'.  Die Optionsvariable '%rnum' enthält
     die Nummer <num>, die an den Präfix '%r' angehängt wird.  Maxima
     erhöht '%rnum' automatisch.  Siehe auch die Systemvariable
     '%rnum_list' für eine Liste der Parameter einer Lösung.

 -- Systemvariable: %rnum_list
     Standardwert: '[]'

     '%rnum_list' ist die Liste der freien Parameter, die von 'solve'
     und 'algsys' in Lösungen eingesetzt werden.  Die Parameter werden
     der Liste '%rnum_list' in der Reihenfolge hinzugefügt, in der sie
     erzeugt werden.

     Beispiele:

          (%i1) solve ([x + y = 3], [x,y]);
          (%o1)              [[x = 3 - %r1, y = %r1]]
          (%i2) %rnum_list;
          (%o2)                       [%r1]
          (%i3) sol : solve ([x + 2*y + 3*z = 4], [x,y,z]);
          (%o3)   [[x = - 2 %r3 - 3 %r2 + 4, y = %r3, z = %r2]]
          (%i4) %rnum_list;
          (%o4)                     [%r2, %r3]
          (%i5) for i : 1 thru length (%rnum_list) do
                  sol : subst (t[i], %rnum_list[i], sol)$
          (%i6) sol;
          (%o6)     [[x = - 2 t  - 3 t  + 4, y = t , z = t ]]
                               2      1           2       1

 -- Optionsvariable: algexact
     Standardwert: 'false'

     Die Optionsvariable 'algexact' kontrolliert die Funktion 'algsys'
     folgendermaßen:

        * Hat 'algexact' den Wert 'true', wird von der Funktion 'algsys'
          stets 'solve' aufgerufen.  Findet 'solve' keine Lösung, wird
          die Funktion 'realroots' aufgerufen.

        * Hat 'algexact' den Wert 'false', wird die Funktion 'solve' nur
          für Gleichungen aufgerufen, die von mehr als einer Variablen
          abhängen und für quadratische oder kubische Gleichungen.

     Der Wert 'true' für 'algexact' garantiert nicht, dass 'algsys' nur
     exakte Lösungen findet.  Findet 'algsys' keine exakten Lösungen,
     versucht 'solve' immer Näherungslösungen zu finden.

     Beispiele:

          (%i1) algexact:true$

          (%i2) algsys([x^5-1],[x]);
                                                sqrt(5)   5
                                         sqrt(- ------- - -)
                               sqrt(5)             2      2    1
          (%o2) [[x = 1], [x = ------- + ------------------- - -],
                                  4               2            4
                                sqrt(5)   5
                         sqrt(- ------- - -)
               sqrt(5)             2      2    1
          [x = ------- - ------------------- - -],
                  4               2            4
                                sqrt(5)   5
                           sqrt(------- - -)
                 sqrt(5)           2      2    1
          [x = - ------- + ----------------- - -],
                    4              2           4
                                sqrt(5)   5
                           sqrt(------- - -)
                 sqrt(5)           2      2    1
          [x = - ------- - ----------------- - -]]
                    4              2           4

          (%i3) algexact:false$

          (%i4) algsys([x^5-1],[x]);
          (%o4) [[x = 1], [x = - .5877852522924731 %i
           - .8090169943749475], [x = .5877852522924731 %i
           - .8090169943749475], [x = .3090169943749475
           - .9510565162951535 %i], [x = .9510565162951535 %i
           + .3090169943749475]]

     Auch wenn die Optionsvariable 'algexact' den Wert 'true' hat, gibt
     'algsys' numerische Näherungslösungen zurück, wenn 'solve' keine
     Lösungen finden kann.

          (%i5) algexact:true$

          (%i6) algsys([x^5-x^3+1],[x]);
          (%o6) [[x = - 1.236505681818182],
          [x = - 0.785423103049449 %i - .3407948661970064],
          [x = 0.785423103049449 %i - .3407948661970064],
          [x = .9590477178927559 - .4283659562541893 %i],
          [x = .4283659562541893 %i + .9590477178927559]]

          (%i7) solve([x^5-x^3+1],[x]);
                                        5    3
          (%o7)                   [0 = x  - x  + 1]

     Für eine quadratische Gleichung wird immer eine exakte Lösung
     zurückgeben.

          (%i8) algsys:true$

          (%i9) algsys([x^2+x-1],[x]);
                           sqrt(5) - 1          sqrt(5) + 1
          (%o9)      [[x = -----------], [x = - -----------]]
                                2                    2
          (%i11) algsys:false$

          (%i12) algsys([x^2+x-1],[x]);
                            sqrt(5) - 1          sqrt(5) + 1
          (%o12)      [[x = -----------], [x = - -----------]]
                                 2                    2

 -- Optionsvariable: algepsilon
     Standardwert: '10^8'

     Kontrolliert die Genauigkeit einer numerischen Lösung der Funktion
     'algsys' für den Fall, dass die Optionsvariable 'realonly' den Wert
     'true' hat, also nur die reellen Lösungen gesucht werden.

     Beispiele:

     Numerische Lösung der Gleichung 'x^3-2' für zwei verschiedene Wert
     für 'algepsilon'.

          (%i1) realonly:true$
          (%i2) algepsilon:10^2;
          (%o2)                          100
          (%i3) algsys([x^3-2],[x]);
          (%o3)                  [[x = 1.26171875]]
          (%i4) algepsilon: 10^8;
          (%o4)                       100000000
          (%i5) algsys([x^3-2],[x]);
          (%o5)               [[x = 1.259921095381759]]

     'algepsilon' hat keinen Einfluss auf die Genauigkeit der Lösung,
     wenn auch die komplexen Lösungen gesucht werden.

          (%i6) realonly:false$
          (%i7) algepsilon: 10^2;
          (%o7)                          100
          (%i8) algsys([x^3-2],[x]);
          (%o8) [[x = - 1.091123635971721 %i - .6299605249474366],
          [x = 1.091123635971721 %i - .6299605249474366],
          [x = 1.259921095381759]]

 -- Funktion: algsys ([<expr_1>, ..., <expr_m>], [<x_1>, ..., <x_n>])
 -- Funktion: algsys ([<eqn_1>, ..., <eqn_m>], [<x_1>, ..., <x_n>])

     Löst ein Gleichungssystem mit den Polynomen <expr_1>, ..., <expr_m>
     oder den Gleichungen <eqn_1>, ..., <eqn_m> für die Variablen <x_1>,
     ..., <x_n>.  Werden Polynome <expr_i> als Argument übergeben,
     werden diese als Gleichungen 'expr_i = 0' interpretiert.  Die
     Anzahl der Gleichungen und Variablen kann verschieden sein.

     'algsys' gibt eine Liste mit den Lösungen zurück.  Jede Lösung ist
     wiederum eine Liste mit den Lösungen für die einzelnen Variablen
     <x_i>, die als Gleichungen angegeben sind.  Kann 'algsys' keine
     Lösung finden, wird eine leere Liste '[]' zurückgegeben.

     Haben die Lösungen freie Parameter, setzt 'algsys' die Symbole
     '%r1', '%r2', ... in die Lösungen ein.  Die freien Parameter werden
     der Liste '%rnum_list' hinzugefügt.  Siehe '%rnum_list'.

     Die Funktion 'algsys' führt die folgenden Schritte aus, um Lösungen
     eines Gleichungssystems zu finden:

       1. Die Gleichungen werden faktorisiert und in Teilsysteme <S_i>
          aufgeteilt.

       2. Für jedes Teilsystem <S_i> werden eine Gleichung <E>, die den
          niedrigsten von Null verschiedenen Grad hat und eine Variable
          <x> ausgewählt.  Dann wird die Resultante der Gleichungen <E>
          und <E_j> für die Variable <x> sowie allen verbleibenden
          Gleichungen <E_j> des Teilsystems <S_i> berechnet.  Dieses
          Verfahren eliminiert die Variable <x> und hat ein neues
          Teilsystem <S_i'> als Ergebnis.  Der Algorithmus wiederholt
          dann den 1.  Schritt.

       3. Besteht das Teilsystem nur noch aus einer Gleichung, hat diese
          Gleichung mehrere Variablen und enthält diese keine
          Gleitkommazahlen, dann wird 'solve' aufgerufen, um eine exakte
          Lösung zu finden.

          Es kann sein, dass 'solve' keine Lösung oder einen sehr großen
          Ausdruck als Lösung findet.

          Auch für Gleichungen, die nur eine Variable enthalten und die
          entweder linear, quadratisch oder quartisch sind sowie keine
          Gleitkommazahlen enthalten, wird 'solve' aufgerufen, um eine
          exakte Lösung zu finden.  Trifft dies nicht zu, wird in dem
          Fall, dass die 'realonly' den Wert 'true' hat, die Funktion
          'realroots'.  Ansonsten wird die Funktion 'allroots'
          aufgerufen.  Die Funktion 'realroots' sucht reelle Lösungen
          der Gleichung, während die Funktion 'allroots' auch komplex
          Lösungen sucht.

          Für den Fall, dass 'realonly' den Wert 'true' hat, wird die
          Genauigkeit einer numerischen Lösung von der Optionsvariablen
          'algepsilon' kontrolliert.

          Hat die Optionsvariable 'algexact' den Wert 'true', wird immer
          die Funktion 'solve' aufgerufen.

       4. Zuletzt werden die erhaltenen Lösungen in das betrachtete
          Teilsystem eingesetzt und der Lösungsalgorithmus mit dem 1.
          Schritt fortgesetzt.

     Tritt beim Lösen des Gleichungssystems eine Gleichung auf, die von
     mehreren Variablen abhängt und Gleitkommazahlen enthält, dann wird
     der Algorithmus mit der Meldung 'algsys cannot solve - system too
     complicated."' abgebrochen.  Ein Näherung mit Gleitkommazahlen kann
     in vorgehenden Schritten auftreten, wenn keine exakten Lösungen
     auffindbar sind.

     Ist das Argument der Funktion 'allroots' kein Polynom, gibt Maxima
     eine Fehlermeldung aus.  Die Lösungen eines Gleichungssystems
     können sehr große Ausdrücke sein.  Obwohl die Lösung reell ist,
     kann die imaginäre Einheit '%i' in den Lösungen enthalten sein.
     Für die weitere Bearbeitung der Lösungen können die Funktionen
     'pickapart' oder 'reveal' hilfreich sein.

     Beispiele:

          (%i1) e1: 2*x*(1 - a1) - 2*(x - 1)*a2;
          (%o1)              2 (1 - a1) x - 2 a2 (x - 1)
          (%i2) e2: a2 - a1;
          (%o2)                        a2 - a1
          (%i3) e3: a1*(-y - x^2 + 1);
                                             2
          (%o3)                   a1 (- y - x  + 1)
          (%i4) e4: a2*(y - (x - 1)^2);
                                                 2
          (%o4)                   a2 (y - (x - 1) )
          (%i5) algsys ([e1, e2, e3, e4], [x, y, a1, a2]);
          (%o5) [[x = 0, y = %r1, a1 = 0, a2 = 0],

                                            [x = 1, y = 0, a1 = 1, a2 = 1]]
          (%i6) e1: x^2 - y^2;
                                        2    2
          (%o6)                        x  - y
          (%i7) e2: -1 - y + 2*y^2 - x + x^2;
                                   2        2
          (%o7)                 2 y  - y + x  - x - 1
          (%i8) algsys ([e1, e2], [x, y]);
                           1            1
          (%o8) [[x = - -------, y = -------],
                        sqrt(3)      sqrt(3)

                  1              1             1        1
          [x = -------, y = - -------], [x = - -, y = - -], [x = 1, y = 1]]
               sqrt(3)        sqrt(3)          3        3

 -- Funktion: allroots (<expr>)
 -- Funktion: allroots (<eqn>)

     Berechnet numerische Näherungen der reellen und komplexen Wurzeln
     des Polynoms <expr> oder der Polynomgleichung <eqn> mit einer
     Variablen.

     Hat der Schalter 'polyfactor' den Wert 'true', wird das Polynom
     über die reellen oder komplexen Zahlen faktorisiert.

     Für den Fall mehrfacher Wurzeln kann 'allroots' ungenaue Ergebnisse
     liefern.  Ist das Polynom reell, kann es sein, dass
     'allroots(%i*<p>)') genauere Approximationen liefern als 'allroots
     (<p>)', da 'allroots' in diesem Fall einen anderen Algorithmus
     verwendet.

     Der Zähler des Arguments der Funktion 'allroots' muss nach
     Anwendung der Funktion 'rat' ein Polynom sein und darf im Nenner
     höchstens eine komplexe Zahl enthalten.  Ist das Argument der
     Funktion 'allroots' kein Polynom, gibt Maxima eine Fehlermeldung.
     Daher wird von der Funktion 'allroots' immer ein äquivalenter,
     jedoch faktorisierter Ausdruck zurückgegeben, wenn die
     Optionsvariable 'polyfactor' den Wert 'true' hat.

     Für komplexe Polynome wird ein Algorithmus von Jenkins und Traub
     verwendet (Algorithm 419, Comm.  ACM, vol.  15, (1972), p.  97).
     Für reelle Polynome wird ein Algorithmus von Jenkins verwendet
     (Algorithm 493, ACM TOMS,vol.  1, (1975), p.178).

     Beispiele:

          (%i1) eqn: (1 + 2*x)^3 = 13.5*(1 + x^5);
                                      3          5
          (%o1)              (2 x + 1)  = 13.5 (x  + 1)
          (%i2) soln: allroots (eqn);
          (%o2) [x = .8296749902129361, x = - 1.015755543828121,

          x = .9659625152196369 %i - .4069597231924075,

          x = - .9659625152196369 %i - .4069597231924075, x = 1.0]
          (%i3) for e in soln
                  do (e2: subst (e, eqn), disp (expand (lhs(e2) - rhs(e2))));
                                - 3.5527136788005E-15

                               - 5.32907051820075E-15

                   4.44089209850063E-15 %i - 4.88498130835069E-15

                  - 4.44089209850063E-15 %i - 4.88498130835069E-15

                                 3.5527136788005E-15

          (%o3)                         done
          (%i4) polyfactor: true$
          (%i5) allroots (eqn);
          (%o5) - 13.5 (x - 1.0) (x - .8296749902129361)

                                     2
           (x + 1.015755543828121) (x  + .8139194463848151 x

           + 1.098699797110288)

 -- Funktion: bfallroots (<expr>)
 -- Funktion: bfallroots (<eqn>)

     Berechnet numerische Näherungen der reellen und komplexen Wurzeln
     des Polynoms <expr> oder der Polynomgleichung <eqn> in einer
     Variable.

     'bfallroots' entspricht der Funktion 'allroots' mit dem
     Unterschied, dass die Funktion 'bfallroots' die Näherungen mit
     großen Gleitkommazahlen berechnet.  Siehe 'allroots'.

     Beispiel:

     Dasselbe Beispiel wie fÃ¼r die Funktion 'allroots'.  Die Ergebnisse
     sind große Gleitkommazahlen.

          (%i1) eqn: (1 + 2*x)^3 = 13.5*(1 + x^5);
                                      3          5
          (%o1)              (2 x + 1)  = 13.5 (x  + 1)
          (%i2) soln: bfallroots(eqn);
          (%o2) [x = 8.296749902129362b-1, x = - 1.015755543828121b0,
          x = 9.65962515219637b-1 %i - 4.069597231924075b-1,
          x = - 9.65962515219637b-1 %i - 4.069597231924075b-1, x = 1.0b0]

 -- Optionsvariable: backsubst
     Standardwert: 'true'

     Hat 'backsubst' den Wert 'false', werden die Lösungen der Funktion
     'linsolve' nicht rücksubstituiert.  Dies kann hilfreich sein, wenn
     die Rücksubstitution zu sehr großen Ausdrücken führt.

     Beispiele:

          (%i1) eq1 : x + y + z = 6$
          (%i2) eq2 : x - y + z = 2$
          (%i3) eq3 : x + y - z = 0$
          (%i4) backsubst : false$
          (%i5) linsolve ([eq1, eq2, eq3], [x,y,z]);
          (%o5)             [x = z - y, y = 2, z = 3]
          (%i6) backsubst : true$
          (%i7) linsolve ([eq1, eq2, eq3], [x,y,z]);
          (%o7)               [x = 1, y = 2, z = 3]

 -- Optionsvariable: breakup
     Standardwert: 'true'

     Hat die Optionsvariablen 'programmode' den Wert 'false' und die
     Optionsvariable 'breakup' den Wert 'true', dann werden für
     gemeinsame Terme in Lösungen von kubischen und quartischen
     Gleichungen Zwischenmarken erzeugt.

     Beispiele:

          (%i1) programmode: false$
          (%i2) breakup: true$
          (%i3) solve (x^3 + x^2 - 1);

                                  sqrt(23)    25 1/3
          (%t3)                  (--------- + --)
                                  6 sqrt(3)   54
          Solution:

                                                sqrt(3) %i   1
                                                ---------- - -
                          sqrt(3) %i   1            2        2   1
          (%t4)    x = (- ---------- - -) %t3 + -------------- - -
                              2        2            9 %t3        3

                                                sqrt(3) %i   1
                                              - ---------- - -
                        sqrt(3) %i   1              2        2   1
          (%t5)    x = (---------- - -) %t3 + ---------------- - -
                            2        2             9 %t3         3

                                             1     1
          (%t6)                  x = %t3 + ----- - -
                                           9 %t3   3
          (%o6)                    [%t4, %t5, %t6]
          (%i6) breakup: false$
          (%i7) solve (x^3 + x^2 - 1);
          Solution:

                       sqrt(3) %i   1
                       ---------- - -
                           2        2        sqrt(23)    25 1/3
          (%t7) x = --------------------- + (--------- + --)
                       sqrt(23)    25 1/3    6 sqrt(3)   54
                    9 (--------- + --)
                       6 sqrt(3)   54

                                                        sqrt(3) %i   1    1
                                                     (- ---------- - -) - -
                                                            2        2    3

                     sqrt(23)    25 1/3  sqrt(3) %i   1
          (%t8) x = (--------- + --)    (---------- - -)
                     6 sqrt(3)   54          2        2

                                                      sqrt(3) %i   1
                                                    - ---------- - -
                                                          2        2      1
                                                + --------------------- - -
                                                     sqrt(23)    25 1/3   3
                                                  9 (--------- + --)
                                                     6 sqrt(3)   54

                      sqrt(23)    25 1/3             1             1
          (%t9)  x = (--------- + --)    + --------------------- - -
                      6 sqrt(3)   54          sqrt(23)    25 1/3   3
                                           9 (--------- + --)
                                              6 sqrt(3)   54
          (%o9)                    [%t7, %t8, %t9]

 -- Funktion: dimension (<eqn>)
 -- Funktion: dimension (<eqn_1>, ..., <eqn_n>)

     'dimen' ist ein Paket für die Dimensionsanalyse.  'load(dimen)'
     lädt dieses Paket.  'demo(dimen)' zeigt eine kleine Demonstration.

 -- Optionsvariable: dispflag
     Standardwert: 'true'

     Hat 'dispflag' den Wert 'false', werden Ausgaben der Funktion
     'solve' unterdrückt.

 -- Funktion: funcsolve (<eqn>, <g>(<t>))

     Das Argument <eqn> ist eine Gleichung, die ein Polynom erster
     Ordnung in den Funktionen '<g>(<t>)' und '<g>(<t+1>)' ist.
     'funcsolve' sucht die rationale Funktion '<g>(<t>)', die Lösung der
     Gleichung <eqn> ist.

     Warnung: Die Funktion ist nur sehr rudimentär implementiert.
     Offensichtliche Verallgemeinerungen fehlen.

     Beispiel:

          (%i1) eqn: (n + 1)*f(n) - (n + 3)*f(n + 1)/(n + 1) =
                (n - 1)/(n + 2);
                                      (n + 3) f(n + 1)   n - 1
          (%o1)        (n + 1) f(n) - ---------------- = -----
                                           n + 1         n + 2
          (%i2) funcsolve (eqn, f(n));

          Dependent equations eliminated:  (4 3)
                                             n
          (%o2)                f(n) = ---------------
                                      (n + 1) (n + 2)

 -- Optionsvariable: globalsolve
     Standardwert: 'false'

     Hat 'globalsolve' den Wert 'true', werden den unbekannten Variablen
     eines linearen Gleichungssystems die Werte der Lösungen der
     Funktionen 'linsolve' und 'solve' zugewiesen.

     Hat 'globalsolve' den Wert 'false', werden den unbekannten
     Variablen eines linearen Gleichungssystems keine Werte zugewiesen.
     Die Lösungen werden als Gleichungen mit den unbekannten Variablen
     ausgedrückt.

     Für andere als lineare Gleichungssysteme wird der Wert von
     'globalsolve' ignoriert.  Die Funktion 'algsys' ignoriert
     'globalsolve' immer.

     Beispiele:

          (%i1) globalsolve: true$
          (%i2) solve ([x + 3*y = 2, 2*x - y = 5], [x, y]);
          Solution

                                           17
          (%t2)                        x : --
                                           7

                                             1
          (%t3)                        y : - -
                                             7
          (%o3)                     [[%t2, %t3]]
          (%i3) x;
                                         17
          (%o3)                          --
                                         7
          (%i4) y;
                                           1
          (%o4)                          - -
                                           7
          (%i5) globalsolve: false$
          (%i6) kill (x, y)$
          (%i7) solve ([x + 3*y = 2, 2*x - y = 5], [x, y]);
          Solution

                                           17
          (%t7)                        x = --
                                           7

                                             1
          (%t8)                        y = - -
                                             7
          (%o8)                     [[%t7, %t8]]
          (%i8) x;
          (%o8)                           x
          (%i9) y;
          (%o9)                           y

 -- Funktion: ieqn (<ie>, <unk>, <tech>, <n>, <guess>)

     'inteqn' ist ein Paket zur Lösung von Integralgleichungen zweiter
     Art der Form

                                 b(x)
                                /
                                [
              p(x) = q(x, p(x), I     w(x, u, p(x), p(u)) du)
                                ]
                                /
                                 a(x)

     und von Integralgleichungen erster Art der Form

                      b(x)
                     /
                     [
              f(x) = I     w(x, u, p(u)) du
                     ]
                     /
                      a(x)

     Das Kommando 'load(inteqn)' lädt das Paket.

     Das erste Argument <ie> ist die Integralgleichung und das Argument
     <unk> die unbekannte Funktion.  Mit dem Argument <tech> wird die
     Methode angegeben, die zur Lösung der Integralgleichung angewendet
     werden soll.  Erhält das Argument <tech> den Wert 'first', wird das
     Ergebnis der ersten erfolgreichen Methode zurückgegeben.  Mit 'all'
     werden alle Methoden angewendet.  Das Argument <n> gibt die
     maximale Anzahl an Termen an, die von den Methoden 'taylor',
     'neumann', 'firstkindseries' oder 'fredseries' verwendet werden.
     <n> ist auch die maximale Tiefe der Rekursion für der
     Differentiationsmethode.  Das Argument <guess> ist der Startwert
     der Methoden 'neumann' oder 'firstkindseries'.

     Die Standardwerte der Argumente sind:

     'unk'
          '<p>(<x>)', wobei <p> die erste im Integranden aufgefundene
          Funktion ist, die Maxima unbekannt ist, und <x> die Variable
          ist, die im Falle einer Integralgleichung der zweiten Art als
          Argument der Funktion <p> außerhalb des Integrals vorgefunden
          wird, oder im Falle einer Integralgleichung der ersten Art die
          einzige andere Variable neben der Integrationsvariable ist.
          Wenn der Versuch fehlschlägt, die Variable <x> zu finden, wird
          der Nutzer nach der unabhängigen Variablen gefragt.

     'tech'
          'first'

     'n'
          '1'

     'guess'
          'none', bewirkt, dass der Ansatz '<f>(<x>)' als Startwert der
          Lösungsmethoden 'neumann' und 'firstkindseries' verwendet
          wird.

     Siehe 'share/integequations/inteqn.usg' für weitere Informationen.

 -- Optionsvariable: ieqnprint
     Standardwert: 'true'

     'ieqnprint' kontrolliert die Ausgabe des Ergebnisses der Funktion
     'ieqn'.  Hat die Optionsvariable 'ieqnprint' den Wert 'true', dann
     hat das Ergebnis der Funktion 'ieqn' die Form '[<solution>,
     <technique used>, <nterms>, <flag>]'.  Ist die Lösung exakt, tritt
     das Element '<flag>' nicht auf.  Ansonsten erhält das Element
     '<flag>' den Wert 'approximate' für eine nicht exakte Lösung und
     den Wert 'incomplete' für eine nicht geschlossene Lösung.  Wurde
     die Lösung mit einer Methode gefunden, die einen Reihenansatz
     verwendet, enthält <nterms> die Anzahl der Terme der Entwicklung.

 -- Funktion: lhs (<expr>)

     Gibt die linke Seite des Ausdrucks <expr> zurück, wenn der Operator
     von <expr> einer der relationalen Operatoren '< <= = # equal
     notequal >= >', einer der Zuweisungsoperatoren ':= ::= : ::' oder
     ein nutzerdefinierter binärer Infix-Operator ist, der mit der
     Funktion 'infix' deklariert wurde.  Die linke Seite des Ausdrucks
     ist für die hier genannten Operatoren das erste Argument.

     Wenn <expr> ein Atom ist oder sein Operator ein anderer als oben
     aufgelistet, gibt 'lhs' den Ausdruck <expr> zurück.  Siehe auch
     'rhs'.

     Beispiele:

          (%i1) e: aa + bb = cc;
          (%o1)                     bb + aa = cc
          (%i2) lhs (e);
          (%o2)                        bb + aa
          (%i3) rhs (e);
          (%o3)                          cc
          (%i4) [lhs (aa < bb), lhs (aa <= bb), lhs (aa >= bb),
                 lhs (aa > bb)];
          (%o4)                   [aa, aa, aa, aa]
          (%i5) [lhs (aa = bb), lhs (aa # bb), lhs (equal (aa, bb)),
                 lhs (notequal (aa, bb))];
          (%o5)                   [aa, aa, aa, aa]
          (%i6) e1: '(foo(x) := 2*x);
          (%o6)                     foo(x) := 2 x
          (%i7) e2: '(bar(y) ::= 3*y);
          (%o7)                    bar(y) ::= 3 y
          (%i8) e3: '(x : y);
          (%o8)                         x : y
          (%i9) e4: '(x :: y);
          (%o9)                        x :: y
          (%i10) [lhs (e1), lhs (e2), lhs (e3), lhs (e4)];
          (%o10)               [foo(x), bar(y), x, x]
          (%i11) infix ("][");
          (%o11)                         ][
          (%i12) lhs (aa ][ bb);
          (%o12)                         aa

 -- Funktion: linsolve ([<expr_1>, ..., <expr_m>], [<x_1>, ..., <x_n>])

     Löst das lineare Gleichungssystem mit den Gleichungen oder
     Polynomen [<expr_1>, ..., <expr_m>] und den Variablen [<x_1>, ...,
     <x_n>].  Jede Gleichung muss ein Polynom in den angegebenen
     Variablen sein.

     Hat die Optionsvariable 'globalsolve' den Wert 'true', werden die
     Lösungen des Gleichungssystems den angegebenen Variablen
     zugewiesen.

     Hat die Optionsvariable 'backsubst' den Wert 'false', führt
     'linsolve' keine Rücksubstitutionen aus.  Dies kann hilfreich sein,
     wenn die Rücksubstitution zu sehr großen Ausdrücken führt.

     Hat die Optionsvariable 'linsolve_params' den Wert 'true', setzt
     'linsolve' für ein unterbestimmtes Gleichungssystem freie Parameter
     in die Lösungen ein, die mit '%r'-Symbolen bezeichnet werden.
     Siehe auch '%rnum' und '%rnum_list'.

     Hat die Optionsvariable 'programmode' den Wert 'false', werden die
     Lösungen von 'linsolve' Zwischenmarken '%t' zugewiesen.  Die
     Zwischenmarken werden als Liste zurückgegeben.

     Beispiele:

          (%i1) e1: x + z = y;
          (%o1)                       z + x = y
          (%i2) e2: 2*a*x - y = 2*a^2;
                                                 2
          (%o2)                   2 a x - y = 2 a
          (%i3) e3: y - 2*z = 2;
          (%o3)                      y - 2 z = 2
          (%i4) [globalsolve: false, programmode: true];
          (%o4)                     [false, true]
          (%i5) linsolve ([e1, e2, e3], [x, y, z]);
          (%o5)            [x = a + 1, y = 2 a, z = a - 1]
          (%i6) [globalsolve: false, programmode: false];
          (%o6)                    [false, false]
          (%i7) linsolve ([e1, e2, e3], [x, y, z]);
          Solution

          (%t7)                       z = a - 1

          (%t8)                        y = 2 a

          (%t9)                       x = a + 1
          (%o9)                    [%t7, %t8, %t9]
          (%i9) ''%;
          (%o9)            [z = a - 1, y = 2 a, x = a + 1]
          (%i10) [globalsolve: true, programmode: false];
          (%o10)                    [true, false]
          (%i11) linsolve ([e1, e2, e3], [x, y, z]);
          Solution

          (%t11)                      z : a - 1

          (%t12)                       y : 2 a

          (%t13)                      x : a + 1
          (%o13)                 [%t11, %t12, %t13]
          (%i13) ''%;
          (%o13)           [z : a - 1, y : 2 a, x : a + 1]
          (%i14) [x, y, z];
          (%o14)                 [a + 1, 2 a, a - 1]
          (%i15) [globalsolve: true, programmode: true];
          (%o15)                    [true, true]
          (%i16) linsolve ([e1, e2, e3], '[x, y, z]);
          (%o16)           [x : a + 1, y : 2 a, z : a - 1]
          (%i17) [x, y, z];
          (%o17)                 [a + 1, 2 a, a - 1]

 -- Optionsvariable: linsolvewarn
     Standardwert: 'true'

     Hat 'linsolvewarn' den Wert 'true', gibt die Funktion 'linsolve'
     gegebenenfalls die Meldung 'Dependent equations eliminated' aus.

 -- Optionsvariable: linsolve_params
     Standardwert: 'true'

     Hat 'linsolve_params' den Wert 'true', setzt die Funktion
     'linsolve' für ein unterbestimmtes Gleichungssystem freie Parameter
     in die Lösungen ein, die mit '%r'-Symbolen bezeichnet werden.
     Siehe auch '%rnum' und '%rnum_list'.

 -- Systemvariable: multiplicities
     Standardwert: 'not_set_yet'

     'multiplicities' ist die Liste der Vielfachheiten der Lösungen, die
     von 'solve', 'realroots' oder 'allroots' zurückgegeben werden.

     Beispiel:

          (%i1) solve(x^2*(x+1)^2, x);
          (%o1)                   [x = - 1, x = 0]
          (%i2) multiplicities;
          (%o2)                        [2, 2]

 -- Funktion: nroots (<p>, <low>, <high>)

     Gibt die Anzahl der reellen Wurzeln des reellen univariaten
     Polynoms <p> im halboffenen Intervall '(<low>, <high>]' zurück.
     Die Grenzen des Intervalls können auch negativ unendlich 'minf'
     oder positiv unendlich 'inf' sein.

     'nroots' verwendet die Methode der Sturm-Sequenzen.

     Beispiel:

          (%i1) p: x^10 - 2*x^4 + 1/2$
          (%i2) nroots (p, -6, 9.1);
          (%o2)                           4

 -- Funktion: nthroot (<p>, <n>)

     Das Argument <p> ist ein Polynom mit ganzzahligen Koeffizienten und
     das Argument <n> eine positive ganze Zahl.  'nthroot' gibt ein
     Polynom q über die ganzen Zahlen zurück, so dass q^n = p gilt.
     Existiert kein derartiges Polynom <q> gibt Maxima eine
     Fehlermeldung aus.  'nthroot' ist wesentlich schneller als die
     Funktionen 'factor' oder 'sqfr'.

 -- Optionsvariable: polyfactor
     Standardwert: 'false'

     Hat die Optionsvariable 'polyfactor' den Wert 'true', werden die
     Lösungen der Funktionen 'allroots' und 'bfallroots' über die
     reellen Zahlen faktorisiert, wenn das Polynom reell ist, und über
     die komplexen Zahlen, wenn das Polynome komplex ist.

     Siehe 'allroots' für ein Beispiel.

 -- Optionsvariable: programmode
     Standardwert: 'true'

     Hat 'programmode' den Wert 'true', geben die Funktionen 'solve',
     'realroots', 'allroots', 'bfallroots' und 'linsolve' die Lösungen
     als Elemente einer Liste zurück.

     Hat 'programmode' den Wert 'false', werden die Lösungen der oben
     genannten Funktionen Zwischenmarken '%t' zugewiesen.  Die Rückgabe
     der Funktionen ist in diesem Fall eine Liste der Zwischenmarken.

 -- Optionsvariable: realonly
     Standardwert: 'false'

     Hat 'realonly' den Wert 'true', gibt 'algsys' nur Lösungen zurück,
     die nicht die imaginäre Einheit '%i' enthalten.

 -- Funktion: realroots (<expr>, <bound>)
 -- Funktion: realroots (<eqn>, <bound>)
 -- Funktion: realroots (<expr>)
 -- Funktion: realroots (<eqn>)

     Computes rational approximations of the real roots of the
     polynomial <expr> or polynomial equation <eqn> of one variable, to
     within a tolerance of <bound>.  Coefficients of <expr> or <eqn>
     must be literal numbers; symbol constants such as '%pi' are
     rejected.

     'realroots' assigns the multiplicities of the roots it finds to the
     global variable 'multiplicities'.

     'realroots' constructs a Sturm sequence to bracket each root, and
     then applies bisection to refine the approximations.  All
     coefficients are converted to rational equivalents before searching
     for roots, and computations are carried out by exact rational
     arithmetic.  Even if some coefficients are floating-point numbers,
     the results are rational (unless coerced to floats by the 'float'
     or 'numer' flags).

     When <bound> is less than 1, all integer roots are found exactly.
     When <bound> is unspecified, it is assumed equal to the global
     variable 'rootsepsilon'.

     When the global variable 'programmode' is 'true', 'realroots'
     returns a list of the form '[x = <x_1>, x = <x_2>, ...]'.  When
     'programmode' is 'false', 'realroots' creates intermediate
     expression labels '%t1', '%t2', ..., assigns the results to them,
     and returns the list of labels.

     Examples:

          (%i1) realroots (-1 - x + x^5, 5e-6);
                                         612003
          (%o1)                     [x = ------]
                                         524288
          (%i2) ev (%[1], float);
          (%o2)                 x = 1.167303085327148
          (%i3) ev (-1 - x + x^5, %);
          (%o3)                - 7.396496210176905E-6

          (%i1) realroots (expand ((1 - x)^5 * (2 - x)^3 * (3 - x)), 1e-20);
          (%o1)                 [x = 1, x = 2, x = 3]
          (%i2) multiplicities;
          (%o2)                       [5, 3, 1]

 -- Funktion: rhs (<expr>)

     Gibt die rechte Seite des Ausdrucks <expr> zurück, wenn der
     Operator von <expr> einer der relationalen Operatoren '< <= = #
     equal notequal >= >', einer der Zuweisungsoperatoren ':= ::= : ::'
     oder ein nutzerdefinierter binärer Infixoperator ist, der mit der
     Funktion 'infix' deklariert wurde.  Die rechte Seite des Ausdrucks
     ist für die hier genannten Operatoren das zweite Argument.

     Ist <expr> ein Atom oder hat der Ausdruck <expr> einen anderen
     Operator als oben angegeben, dann ist das Ergebnis '0'.  Siehe auch
     'lhs'.

     Beispiele:

          (%i1) e: aa + bb = cc;
          (%o1)                     bb + aa = cc
          (%i2) lhs (e);
          (%o2)                        bb + aa
          (%i3) rhs (e);
          (%o3)                          cc
          (%i4) [rhs (aa < bb), rhs (aa <= bb), rhs (aa >= bb),
                 rhs (aa > bb)];
          (%o4)                   [bb, bb, bb, bb]
          (%i5) [rhs (aa = bb), rhs (aa # bb), rhs (equal (aa, bb)),
                 rhs (notequal (aa, bb))];
          (%o5)                   [bb, bb, bb, bb]
          (%i6) e1: '(foo(x) := 2*x);
          (%o6)                     foo(x) := 2 x
          (%i7) e2: '(bar(y) ::= 3*y);
          (%o7)                    bar(y) ::= 3 y
          (%i8) e3: '(x : y);
          (%o8)                         x : y
          (%i9) e4: '(x :: y);
          (%o9)                        x :: y
          (%i10) [rhs (e1), rhs (e2), rhs (e3), rhs (e4)];
          (%o10)                  [2 x, 3 y, y, y]
          (%i11) infix ("][");
          (%o11)                         ][
          (%i12) rhs (aa ][ bb);
          (%o12)                         bb

 -- Optionsvariable: rootsepsilon
     Standardwert: '1.0e-7'

     'rootsepsilon' ist die Toleranz, die den Vertrauensbereich für die
     von der Funktion 'realroots' gefundenen Wurzeln festsetzt.

 -- Funktion: solve (<expr>, <x>)
 -- Funktion: solve (<expr>)
 -- Funktion: solve ([<eqn_1>, ..., <eqn_n>], [<x_1>, ..., <x_n>])

     Löst eine algebraische Gleichung <expr> nach der Variablen <x> auf.
     Wenn <expr> keine Gleichung ist, wird die Gleichung '<expr> = 0'
     angenommen.  <x> kann eine Funktion wie zum Beispiel 'f(x)') sein
     oder ein allgemeiner Ausdruck.  Ausgenommen sind Summen und
     Produkte.  Hat die Gleichung nur eine Variable, braucht diese nicht
     angegeben zu werden.  <expr> kann ein rationaler Ausdruck sein und
     trigonometrische Funktionen, Exponentialfunktionen und andere
     Funktionen enthalten.  Zur Lösung wird die folgende Methode
     verwendet:

       1. Sei <E> ein Ausdruck und <X> die Variable.  Ist <E> linear in
          <X>, dann kann die Gleichung sofort nach der Variablen 'X'
          aufgelöst werden.  Hat <E> die Form 'A*X^N + B', dann ist das
          Ergebnis '(-B/A)^1/N)' multipliziert mit der 'N'-ten
          Einheitswurzel.

       2. Ist <E> nicht linear in <X>, wird der größte gemeinsame Teiler
          <N> der Exponenten der Variable <X> bestimmt.  Die Exponenten
          der Variablen werden durch <N> dividiert und die Multiplizität
          der Lösungen mit <N> multipliziert.  'solve' wird erneut für
          den Ausdruck aufgerufen.  Kann <E> faktorisiert werden, wird
          'solve' für jeden Faktor aufgerufen.  Zuletzt prüft 'solve',
          ob einer der Algorithmen für quadratische, kubische oder
          quartische Gleichungen angewendet werden kann.

       3. Ist <E> ein Polynom in einer Funktion 'F(X)' mit <X> als der
          Variablen, wird zunächst die Lösung des Polynoms für 'F(X)'
          gesucht.  Ist <C> eine solche Lösung, kann die Gleichung
          'F(X)=C' gelöst werden, wenn die Umkehrfunktion zu 'F(X)'
          bekannt ist.

     Hat die Optionsvariable 'breakup' den Wert 'false', werden die
     Lösungen von kubischen und quartischen Gleichungen nicht in
     gemeinsame Teilausdrücke zerlegt.

     Die Systemvariable 'multiplicities' enthält eine Liste mit den
     Vielfachheiten der einzelnen Lösungen.

     'solve ([<eqn_1>, ..., <eqn_n>], [<x_1>, ..., <x_n>])' löst ein
     Gleichungssystem mit den Polynomen <eqn_1>, ..., <eqn_n> für die
     Variablen <x_1>, ..., <x_n>.  Die Polynome können linear oder
     nichtlinear sein.  Um das System zu lösen, werden die Funktionen
     'linsolve' oder 'algsys' aufgerufen.  Das Ergebnis ist eine Liste
     mit den Lösungen.  Ist die Anzahl der Gleichungen gleich der Anzahl
     der Variablen des Systems, kann das Argument mit der Liste der
     Variablen entfallen.

     Hat die Optionsvariable 'programmode' den Wert 'false' ist, zeigt
     'solve' die Lösungen mit Hilfe von Zwischenmarken ('%t') an und
     gibt die Liste der Marken zurück.

     Hat die Optionsvariable 'globalsolve' den Wert 'true', werden den
     unbekannten Variablen eines linearen Gleichungssystems die Werte
     der Lösung der Funktionen 'linsolve' und 'solve' zugewiesen.

     Beispiele:

          (%i1) solve (asin (cos (3*x))*(f(x) - 1), x);

          SOLVE is using arc-trig functions to get a solution.
          Some solutions will be lost.
                                      %pi
          (%o1)                  [x = ---, f(x) = 1]
                                       6
          (%i2) ev (solve (5^f(x) = 125, f(x)), solveradcan);
                                          log(125)
          (%o2)                   [f(x) = --------]
                                           log(5)
          (%i3) [4*x^2 - y^2 = 12, x*y - x = 2];
                                2    2
          (%o3)             [4 x  - y  = 12, x y - x = 2]
          (%i4) solve (%, [x, y]);
          (%o4) [[x = 2, y = 2], [x = .5202594388652008 %i

           - .1331240357358706, y = .0767837852378778

           - 3.608003221870287 %i], [x = - .5202594388652008 %i

           - .1331240357358706, y = 3.608003221870287 %i

           + .0767837852378778], [x = - 1.733751846381093,

          y = - .1535675710019696]]
          (%i5) solve (1 + a*x + x^3, x);
                                                 3
                        sqrt(3) %i   1   sqrt(4 a  + 27)   1 1/3
          (%o5) [x = (- ---------- - -) (--------------- - -)
                            2        2      6 sqrt(3)      2

                  sqrt(3) %i   1
                 (---------- - -) a
                      2        2
           - --------------------------, x =
                        3
                sqrt(4 a  + 27)   1 1/3
             3 (--------------- - -)
                   6 sqrt(3)      2

                                    3
           sqrt(3) %i   1   sqrt(4 a  + 27)   1 1/3
          (---------- - -) (--------------- - -)
               2        2      6 sqrt(3)      2

                   sqrt(3) %i   1
                (- ---------- - -) a
                       2        2
           - --------------------------, x =
                        3
                sqrt(4 a  + 27)   1 1/3
             3 (--------------- - -)
                   6 sqrt(3)      2
                   3
           sqrt(4 a  + 27)   1 1/3               a
          (--------------- - -)    - --------------------------]
              6 sqrt(3)      2                  3
                                        sqrt(4 a  + 27)   1 1/3
                                     3 (--------------- - -)
                                           6 sqrt(3)      2
          (%i6) solve (x^3 - 1);
                       sqrt(3) %i - 1        sqrt(3) %i + 1
          (%o6)   [x = --------------, x = - --------------, x = 1]
                             2                     2
          (%i7) solve (x^6 - 1);
                     sqrt(3) %i + 1      sqrt(3) %i - 1
          (%o7) [x = --------------, x = --------------, x = - 1,
                           2                   2

                               sqrt(3) %i + 1        sqrt(3) %i - 1
                         x = - --------------, x = - --------------, x = 1]
                                     2                     2
          (%i8) ev (x^6 - 1, %[1]);
                                                6
                                (sqrt(3) %i + 1)
          (%o8)                 ----------------- - 1
                                       64
          (%i9) expand (%);
          (%o9)                           0
          (%i10) x^2 - 1;
                                        2
          (%o10)                       x  - 1
          (%i11) solve (%, x);
          (%o11)                  [x = - 1, x = 1]
          (%i12) ev (%th(2), %[1]);
          (%o12)                          0

     Die Symbole '%r' bezeichnen freie Konstanten einer Lösung.  Siehe
     'algsys' und '%rnum_list' für mehr Informationen.

          (%i1) solve([x+y=1,2*x+2*y=2],[x,y]);

          solve: dependent equations eliminated: (2)
          (%o1)                      [[x = 1 - %r1, y = %r1]]

 -- Optionsvariable: solvedecomposes
     Standardwert: 'true'

     Hat 'solvedecomposes' den Wert 'true', ruft 'solve' die Funktion
     'polydecomp' auf, um Polynome zu zerlegen.

 -- Optionsvariable: solveexplicit
     Standardwert: 'false'

     Hat 'solveexplicit' den Wert 'true', gibt die Funktion 'solve'
     keine impliziten Lösungen der Form 'F(x) = 0' zurück.

     Beispiel:

          (%i1) solveexplicit:false;
          (%o1)                         false
          (%i2) solve(gamma(x)*x^3-1);
                                     3      1
          (%o2)                    [x  = --------]
                                         gamma(x)
          (%i3) solveexplicit:true;
          (%o3)                         true
          (%i4) solve(gamma(x)*x^3-1);
          (%o4)                          []

 -- Optionsvariable: solvefactors
     Standardwert: 'true'

     Hat 'solvefactors' den Wert 'false', versucht die Funktion 'solve'
     nicht, den Ausdruck zu faktorisieren.  Das Setzen der
     Optionsvariable 'solvefactors' auf den Wert 'false' kann notwendig
     sein, wenn die Faktorisierung nicht benötigt wird, damit 'solve'
     eine Lösung findet.

 -- Optionsvariable: solvenullwarn
     Standardwert: 'true'

     Hat 'solvenullwarn' den Wert 'true', gibt die Funktion 'solve' eine
     Warnmeldung aus, wenn keine Gleichungen oder keine Variablen als
     Argument übergeben wurden.

     Beispiel:

          (%i1) solvenullwarn:true;
          (%o1)                         true
          (%i2) solve(x^2*y+1,[]);

          solve: variable list is empty, continuing anyway.
          (%o2)                          []
          (%i3) solvenullwarn:false;
          (%o3)                         false
          (%i4) solve(x^2*y+1,[]);
          (%o4)                          []

 -- Optionsvariable: solveradcan
     Standardwert: 'false'

     Hat 'solveradcan' den Wert 'true', ruft 'solve' die Funktion
     'radcan' auf, um Ausdrücke zu vereinfachen, die
     Exponentialfunktionen und Logarithmen enthalten.

 -- Optionsvariable: solvetrigwarn
     Standardwert: 'true'

     Hat 'solvetrigwarn' den Wert 'true', gibt die Funktion 'solve' eine
     Warnung aus, wenn inverse trigonometrische Funktionen genutzt
     werden, um Lösungen zu finden.  In diesem Fall können Lösungen
     verloren gehen.

     Beispiel:

          (%i1) solvetrigwarn:true;
          (%o1)                         true
          (%i2) solve(cos(x)+1);

          solve: using arc-trig functions to get a solution.
          Some solutions will be lost.
          (%o2)                       [x = %pi]
          (%i3) solvetrigwarn:false;
          (%o3)                         false
          (%i4) solve(cos(x)+1);
          (%o4)                       [x = %pi]


File: maxima.info,  Node: Lineare Algebra,  Next: Tensoren,  Prev: Gleichungen,  Up: Top

19 Lineare Algebra
******************

* Menu:

* Einführung in die lineare Algebra::
* Funktionen und Variablen der linearen Algebra::


File: maxima.info,  Node: Einführung in die lineare Algebra,  Next: Funktionen und Variablen der linearen Algebra,  Prev: Lineare Algebra,  Up: Lineare Algebra

19.1 Einführung in die lineare Algebra
======================================

* Menu:

* Nicht-kommutative Multiplikation::
* Vektoren::
* Eigenwerte::


File: maxima.info,  Node: Nicht-kommutative Multiplikation,  Next: Vektoren,  Prev: Einführung in die lineare Algebra,  Up: Einführung in die lineare Algebra

19.1.1 Nicht-kommutative Multiplikation
---------------------------------------

Der Operator '.' repräsentiert die nichtkommutative Multiplikation oder
das Skalarprodukt.  Sind die Argumente 1-spaltige oder 1-reihige
Matrizen 'a' und 'b', dann ist der Ausdruck 'a . b' äquivalent zu
'sum(a[i]*b[i], i, 1, length(a))'.  Sind 'a' und 'b' nicht komplex, dann
ist der vorhergende Ausdruck das Skalarprodukt von 'a' und 'b'.  Das
Skalarprodukt ist als 'conjugate(a) . b' definiert, wenn 'a' und 'b'
komplex sind.  Die Funktion 'innerproduct' im Paket 'eigen' stellt das
komplexe Skalarprodukt zur Verfügung.

Sind die Argumente 'a' und 'b' allgemeine Matrizen, dann ist das
Ergebnis der nichtkommutativen Multiplikation das Matrizprodukt der
Argumente.  Die Anzahl der Zeilen der Matrix 'b' muss gleich der Anzahl
der Spalten der Matrix 'a' sein.  Das Ergebnis ist eine Matrix, deren
Anzahl der Zeilen der der Matrix 'a' entspricht und deren Anzahl der
Spalten der der Matrix 'b' entspricht.

Um den nichtkommutativen Operator '.' vom Dezimalpunkt einer
Gleitkommazahl zu unterscheiden, kann es notwendig sein, dem Operator
ein Leerzeichen voranzustellen und folgen zu lassen.  Zum Beispiel ist
'5.e3' die Gleitkommazahl '5000.0' und '5 . e3' ist '5' multipliziert
mit der Variablen 'e3'.

Verschiedene Schalter kontrollieren die Vereinfachung der
nichtkommutativen Multiplikation.  Zu diesen gehören:

   dot            dot0nscsimp     dot0simp
   dot1simp       dotassoc        dotconstrules
   dotdistrib     dotexptsimp     dotident
   dotscrules


File: maxima.info,  Node: Vektoren,  Next: Eigenwerte,  Prev: Nicht-kommutative Multiplikation,  Up: Einführung in die lineare Algebra

19.1.2 Vektoren
---------------

'vect' ist ein Paket mit Funktionen der Vektoranalysis.  Mit dem
Kommando 'load(vect)' wird das Paket geladen.  Das Kommando 'demo(vect)'
zeigt Beispiele.

Das Paket enthält Funktionen, um Ausdrücke mit nicht-kommutativen
Multiplikationen und Kreuzprodukten sowie Gradienten, Divergenzen,
Rotationen und Laplace-Operatoren zu vereinfachen.  Die Vereinfachung
dieser Operatoren wird von verschiedenen Schaltern kontrolliert.
Weiterhin können die Ergebnisse in verschiedenen Koordinatensystemen
berechnet werden.  Mit weiteren Funktionen kann das Skalarpotential oder
das Vektorpotential eines Feldes bestimmt werden.

Das Paket 'vect' enthält die folgenden Funktionen: 'vectorsimp',
'scalefactors', 'express', 'potential' und 'vectorpotential'.


File: maxima.info,  Node: Eigenwerte,  Prev: Vektoren,  Up: Einführung in die lineare Algebra

19.1.3 Eigenwerte
-----------------

Das Paket 'eigen' enthält verschiedene Funktionen, um symbolisch
Eigenwerte und Eigenvektoren zu bestimmen.  Maxima lädt dieses Paket
automatisch, wenn eine der Funktionen dieses Pakets genutzt wird.  Das
Paket kann auch mit dem Kommando 'load(eigen)' geladen werden.

Das Kommando 'demo(eigen)' zeigt Beispiele für das Paket.  Die Beispiele
können auch mit dem Kommando 'batch(eigen' angezeigt werden.  In diesem
Fall wartet Maxima zwischen den einzelnen Beispielen auf die Eingabe des
Nutzers.

Das Paket 'eigen' enthält die folgenden Funktionen:

   innerproduct       unitvector            columnvector
   gramschmidt        eigenvalues           eigenvectors
   uniteigenvectors   similaritytransform


File: maxima.info,  Node: Funktionen und Variablen der linearen Algebra,  Prev: Einführung in die lineare Algebra,  Up: Lineare Algebra

19.2 Funktionen und Variablen der linearen Algebra
==================================================

 -- Funktion: addcol (<M>, <list_1>, ..., <list_n>)

     Hängt eine oder mehrere Spalten, die als Listen <list_1>, ...,
     <list_n> übergeben werden, an die Matrix <M> an.

     Beispiel:

          (%i1) M:matrix([a,b],[c,d]);
                                      [ a  b ]
          (%o1)                       [      ]
                                      [ c  d ]
          (%i2) addcol(M,[1,2],[x,y]);
                                   [ a  b  1  x ]
          (%o2)                    [            ]
                                   [ c  d  2  y ]

 -- Funktion: addrow (<M>, <list_1>, ..., <list_n>)

     Hängt eine oder mehrere Zeilen, die als Listen <list_1>, ...,
     <list_n> übergeben werden, an die Matrix <M> an.

     Beispiel:

          (%i1) M:matrix([a,b],[c,d]);
                                      [ a  b ]
          (%o1)                       [      ]
                                      [ c  d ]
          (%i2) addrow(M,[1,2],[x,y]);
                                      [ a  b ]
                                      [      ]
                                      [ c  d ]
          (%o2)                       [      ]
                                      [ 1  2 ]
                                      [      ]
                                      [ x  y ]

 -- Funktion: adjoint (<M>)

     Gibt die adjungierte der Matrix <M> zurück.

 -- Funktion: augcoefmatrix ([<eqn_1>, ..., <eqn_m>], [<x_1>, ...,
          <x_n>])

     Gibt die erweiterte Koeffizientenmatrix für die Variablen <x_1>,
     ..., <x_n> und dem linearen Gleichungssystem <eqn_1>, ..., <eqn_m>.
     Die erweiterte Koeffizientenmatrix entsteht, wenn an die
     Koeffizientenmatrix des Gleichungssystems die Spalte mit der
     rechten Seite des Gleichungssystems angefügt wird.

     Beispiel:

          (%i1) m: [2*x - (a - 1)*y = 5*b, c + b*y + a*x = 0]$
          (%i2) augcoefmatrix (m, [x, y]);
                                 [ 2  1 - a  - 5 b ]
          (%o2)                  [                 ]
                                 [ a    b      c   ]

 -- Funktion: charpoly (<M>, <x>)

     Gibt das charakteristische Polynom der Matrix <M> für die Variable
     <x> zurück.  Das charakterische Polynom wird als 'determinant(<M> -
     diagmatrix(length (<M>), <x>))' berechnet.

     Beispiel:

          (%i1) a: matrix ([3, 1], [2, 4]);
                                      [ 3  1 ]
          (%o1)                       [      ]
                                      [ 2  4 ]
          (%i2) expand (charpoly (a, lambda));
                                     2
          (%o2)                lambda  - 7 lambda + 10
          (%i3) (programmode: true, solve (%));
          (%o3)               [lambda = 5, lambda = 2]
          (%i4) matrix ([x1], [x2]);
                                       [ x1 ]
          (%o4)                        [    ]
                                       [ x2 ]
          (%i5) ev (a . % - lambda*%, %th(2)[1]);
                                    [ x2 - 2 x1 ]
          (%o5)                     [           ]
                                    [ 2 x1 - x2 ]
          (%i6) %[1, 1] = 0;
          (%o6)                     x2 - 2 x1 = 0
          (%i7) x2^2 + x1^2 = 1;
                                      2     2
          (%o7)                     x2  + x1  = 1
          (%i8) solve ([%th(2), %], [x1, x2]);
                            1               2
          (%o8) [[x1 = - -------, x2 = - -------],
                         sqrt(5)         sqrt(5)

                                                       1             2
                                              [x1 = -------, x2 = -------]]
                                                    sqrt(5)       sqrt(5)

 -- Funktion: coefmatrix ([<eqn_1>, ..., <eqn_m>], [<x_1>, ..., <x_n>])

     Gibt die Koeffizientenmatrix für die Variablen <x_1>, ..., <x_n>
     des linearen Gleichungssystem <eqn_1>, ..., <eqn_m> zurück.

     Beispiel:

          (%i1) coefmatrix([2*x-(a-1)*y+5*b = 0, b*y+a*x = 3], [x,y]);
                                           [ 2  1 - a ]
          (%o1)                            [          ]
                                           [ a    b   ]

 -- Funktion: col (<M>, <i>)

     Gibt die <i>-te Spalte der Matrix <M> zurück.  Das Ergebnis ist
     eine Matrix.

     Beispiel:

          (%i1) M:matrix([1,2,3],[a,b,c]);
                                     [ 1  2  3 ]
          (%o1)                      [         ]
                                     [ a  b  c ]
          (%i2) col(M,2);
                                        [ 2 ]
          (%o2)                         [   ]
                                        [ b ]

 -- Funktion: columnvector (<L>)
 -- Funktion: covect (<L>)

     Gibt eine Matrix mit einer Spalte zurück, die die Elemente der
     Liste <L> enthält.

     'covect' ist ein Alias-Name für die Funktion 'columnvector'.  Das
     Kommando 'load(eigen)' lädt die Funktion.

     Beispiel:

          (%i1) load(eigen)$

          (%i2) columnvector ([aa, bb, cc]);
                                       [ aa ]
                                       [    ]
          (%o2)                        [ bb ]
                                       [    ]
                                       [ cc ]

 -- Funktion: copymatrix (<M>)

     Gibt eine Kopie der Matrix <M> zurück.

     Die Zuweisung wie zum Beispiel 'm2: m1' kopiert die Matrix 'm1'
     nicht.  Wird nach dieser Zuweisung die Matrix 'm2' geändert, wird
     auch die Matrix 'm1' geändert.  Um eine Kopie zu erhalten, muss
     'm2: copymatrix(m1)' ausgeführt werden.

 -- Funktion: determinant (<M>)

     Berechnet die Determinate der Matrix <M>.  Die angewendete Methode
     ist vergleichbar mit dem Gauß-Verfahren.

     'determinat' wird von den Schaltern 'ratmx' und 'sparse'
     kontrolliert.  Haben beide Schalter den Wert 'true', wird ein
     spezieller Algorithmus für schwachbesetzte Matrizen aufgerufen.

 -- Optionsvariable: detout
     Standardwert: 'false'

     Hat 'detout' den Wert 'true', wird die Determinate einer Matrix,
     für die die inverse Matrix berechnet wird, aus der Matrix
     herausmultipliziert.

     Damit dieser Schalter einen Effekt hat, müssen die Optionsvariablen
     'doallmxops' und 'doscmxops' den Wert 'false' haben.

     Beispiele:

          (%i1) m: matrix ([a, b], [c, d]);
                                      [ a  b ]
          (%o1)                       [      ]
                                      [ c  d ]
          (%i2) detout: true$
          (%i3) doallmxops: false$
          (%i4) doscmxops: false$
          (%i5) invert (m);
                                    [  d   - b ]
                                    [          ]
                                    [ - c   a  ]
          (%o5)                     ------------
                                     a d - b c

 -- Funktion: diagmatrix (<n>, <x>)

     Gibt eine <n>-dimensionale Diagonalmatrix zurück, deren
     Diagonalelemente alle den Wert <x> haben.

     <n> muss zu einer ganzen Zahl auswerten.  Ansonsten meldet Maxima
     einen Fehler.

     <x> kann ein beliebiger Ausdruck einschließlich einer Matrix sein.
     Ist <x> eine Matrix, dann wird diese nicht kopiert.

 -- Optionsvariable: doallmxops
     Standardwert: 'true'

     Hat 'doallmxops' den Wert 'true', werden Matrixoperationen
     ausgeführt.  Ist der Wert 'false', werden nur die Matrixoperationen
     ausgeführt, die mit den einzelnen 'dot'-Schaltern eingeschaltet
     sind.

 -- Optionsvariable: domxexpt
     Standardwert: 'true'

     Hat 'domxexpt' den Wert 'true', wird die Exponentiation 'exp(<M>)',
     wobei <M> eine Matrix ist, elementweise für jedes einzelne
     Matrixelement ausgeführt, so dass für jedes Element der Matrix gilt
     'exp (m[i,j])'.  Ansonsten wird die Exponentiation als 'exp
     (<ev(M)>' ausgewertet.

     'domxexpt' beeinflußt alle Ausdrücke der Form '<a>^<b>', wobei <a>
     eine Konstante oder ein skalarer Ausdruck und <b> eine Liste oder
     Matrix ist.

     Beispiele:

          (%i1) m: matrix ([1, %i], [a+b, %pi]);
                                   [   1    %i  ]
          (%o1)                    [            ]
                                   [ b + a  %pi ]
          (%i2) domxexpt: false$
          (%i3) (1 - c)^m;
                                       [   1    %i  ]
                                       [            ]
                                       [ b + a  %pi ]
          (%o3)                 (1 - c)
          (%i4) domxexpt: true$
          (%i5) (1 - c)^m;
                            [                      %i  ]
                            [    1 - c      (1 - c)    ]
          (%o5)             [                          ]
                            [        b + a         %pi ]
                            [ (1 - c)       (1 - c)    ]

 -- Optionsvariable: domxmxops
     Standardwert: 'true'

     Hat 'domxmxops' den Wert 'true', werden allen Matrix-Matrix und
     Matrix-Listen-Operationen ausgeführt.

 -- Optionsvariable: domxnctimes
     Standardwert: 'false'

     Hat 'domxnctimes' den Wert 'true', werden nichtkommutative Produkte
     von Matrizen ausgeführt.

 -- Optionsvariable: doscmxops
     Standardwert: 'false'

     Hat 'doscmxops' den Wert 'true', werden Skalar-Matrix-Operationen
     ausgeführt.

 -- Optionsvariable: doscmxplus
     Standardwert: 'false'

     Hat 'doscmxplus' den Wert 'true', haben Skalar-Matrix-Operationen
     eine Matrix als Ergebnis.  Dieser Schalter ist nicht unter
     'doallmxops' subsumiert.

 -- Optionsvariable: dot0nscsimp
     Standardwert: 'true'

     Hat 'dot0nscsimp' den Wert 'true', werden nichtkommutative Produkte
     mit einer Null und einem nichtskalaren Term zu einem kommutativen
     Produkt vereinfacht.

 -- Optionsvariable: dot0simp
     Standardwert: 'true'

     Hat 'dot0simp' den Wert 'true', werden nichtkommutative Produkte
     mit einer Null und einem skalaren Term zu einem kommutatitiven
     Produkt vereinfacht.

 -- Optionsvariable: dot1simp
     Standardwert: 'true'

     Hat 'dot1simp' den Wert 'true', werden nichtkommutative Produkte
     mit einer Eins und einem anderen Term zu einem kommutativen Produkt
     vereinfacht.

 -- Optionsvariable: dotassoc
     Standardwert: 'true'

     Hat 'dotassoc' den Wert 'true', vereinfacht Maxima ein Ausdruck
     '(A.B).C' zu 'A.(B.C)'.

 -- Optionsvariable: dotconstrules
     Standardwert: 'true'

     Hat 'dotconstrules' den Wert 'true', werden nichtkommutative
     Produkte einer Konstanten und eines Termes zu einem kommutativen
     Produkt vereinfacht.  Die folgenden Optionsvariablen 'dot0simp',
     'dot0nscsimp' und 'dot1simp' erhalten den Wert 'true', wenn
     'construles' eingeschaltet wird.

 -- Optionsvariable: dotdistrib
     Standardwert: 'false'

     Hat 'dotdistrib' den Wert 'true', vereinfacht Maxima einen Ausdruck
     'A.(B + C)' zu 'A.B + A.C'.

 -- Optionsvariable: dotexptsimp
     Standardwert: 'true'

     Hat 'dotexptsimp' den Wert 'true', vereinfacht Maxima einen
     Ausdruck 'A.A' zu 'A^^2'.

 -- Optionsvariable: dotident
     Standardwert: 1

     'dotident' ist der Wert der für den Ausdruck 'X^^0' zurückgegeben
     wird.

 -- Optionsvariable: dotscrules
     Standardwert: 'false'

     Hat 'dotscrules' den Wert 'true', vereinfacht Maxima Ausdrücke
     'A.SC' oder 'SC.A' zu 'SC*A' und 'A.(SC*B)' zu 'SC*(A.B)'.

 -- Funktion: echelon (<M>)

     Gibt die Matrix <m> in ihrer Stufenform zurück, wie sie im
     Gaußschen Eliminationsverfahren auftritt.

     Im Unterschied zur Funktion 'triangularize' wird die Matrix so
     normiert, dass die Hauptdiagonalelemente den Wert 1 haben.

     'lu_factor' und 'cholesky' sind weitere Funktionen, um
     Dreiecksmatrizen zu erhalten.

     Beispiel:

          (%i1) M: matrix ([3, 7, aa, bb], [-1, 8, 5, 2], [9, 2, 11, 4]);
                                 [  3   7  aa  bb ]
                                 [                ]
          (%o1)                  [ - 1  8  5   2  ]
                                 [                ]
                                 [  9   2  11  4  ]
          (%i2) echelon (M);
                            [ 1  - 8  - 5      - 2     ]
                            [                          ]
                            [         28       11      ]
                            [ 0   1   --       --      ]
          (%o2)             [         37       37      ]
                            [                          ]
                            [              37 bb - 119 ]
                            [ 0   0    1   ----------- ]
                            [              37 aa - 313 ]

 -- Funktion: eigenvalues (<M>)
 -- Funktion: eivals (<M>)

     Gibt eine Liste mit den Eigenwerten der Matrix <M> und deren
     Multiplizitäten zurück.  Die erste Teilliste enthält die
     Eigenwerte, die zweite deren Multiplizitäten.

     'eivals' ist ein Alias-Name der Funktion 'eigenvalues'.

     'eigenvalues' ruft die Funktion 'solve' auf, um die Nullstellen des
     charakeristischen Polynoms der Matrix zu finden.  Wenn 'solve'
     keine Nullstellen finden kann, funktionieren einige Funktionen des
     Pakets nicht.  Dies trifft nicht auf die Funktionen 'innerproduct',
     'unitvector', 'columnvector' und 'gramschmidt' zu.

     Die Eigenwerte, die 'solve' findet, können sehr komplizierte
     Ausdrücke sein.  Es kann möglich sein, solche Ausdrücke weiter zu
     vereinfachen.

     Das Paket 'eigen' wird automatisch geladen, wenn eine der
     Funktionen 'eigenvalues' oder 'eigenvectors' aufgerufen wird.

 -- Funktion: eigenvectors (<M>)
 -- Funktion: eivects (<M>)

     Berechnet die Eigenvektoren der Matrix <M>.  Die Rückgabe ist eine
     Liste, die zwei weitere Listen enthält.  Die erste Liste enthält
     die Eigenwerte der Matrix <m> und deren Multiplizitäten.  Die
     zweite Liste enthält die Eigenvektoren.

     'eivects' ist ein Alias-Name der Funktion 'eigenvectors'.

     Das Paket 'eigen' wird automatisch geladen, wenn die Funktionen
     'eigenvalues' oder 'eigenvectors' aufgerufen werden.

     Folgende Schalter kontrollieren 'eigenvectors':

     'nondiagonalizable'
          'nondiagonalizabel' hat den Wert 'true' oder 'false' nach
          Rückkehr der Funktion 'eigenvectros' abhängig davon, ob die
          Matrix diagonalisierbar ist oder nicht.

     'hermitianmatrix'
          Hat 'hermitianmatrix' den Wert 'true', werden die entarteten
          Eigenvektoren einer Hermitischen Matrix mit dem
          Gram-Schmidt-Verfahren orthogonalisiert.

     'knowneigvals'
          Hat 'knowneigvals' den Wert 'true', werden die Eigenwerte der
          Matrix von den Funktionen des Paketes 'eigen' als bekannt
          angenommen.  Die Eigenwerte sind in diesem Fall in der Liste
          'listeigvals' abgespeichert.  Die Liste 'listeigvals' muss
          dieselbe Form haben, wie die Rückgabe der Funktion
          'eigenvalues'.

     Die Eigenvektoren werden von der Funktion 'algsys' berechnet.  Es
     ist möglich, dass 'algsys' die Eigenvektoren nicht findet.  In
     diesem Fall können möglicherweise zunächst die Eigenwerte bestimmt
     und weiter vereinfacht werden.  Dannach kann die Funktion
     'eigenvectors' mit dem Schalter 'knowneigvals' aufgerufen werden.

     Siehe auch 'eigenvalues'.

     Beispiele:

     Eine Matrix, die einen Eigenvektor zu jedem Eigenwert hat.

          (%i1) M1 : matrix ([11, -1], [1, 7]);
                                     [ 11  - 1 ]
          (%o1)                      [         ]
                                     [ 1    7  ]
          (%i2) [vals, vecs] : eigenvectors (M1);
          (%o2) [[[9 - sqrt(3), sqrt(3) + 9], [1, 1]],
                                  [[[1, sqrt(3) + 2]], [[1, 2 - sqrt(3)]]]]
          (%i3) for i thru length (vals[1]) do disp (val[i] = vals[1][i],
            mult[i] = vals[2][i], vec[i] = vecs[i]);
                                 val  = 9 - sqrt(3)
                                    1

                                      mult  = 1
                                          1

                              vec  = [[1, sqrt(3) + 2]]
                                 1

                                 val  = sqrt(3) + 9
                                    2

                                      mult  = 1
                                          2

                              vec  = [[1, 2 - sqrt(3)]]
                                 2

          (%o3)                         done

     Eine Matrix, die zwei Eigenvektoren zu jedem Eigenwert hat.

          (%i1) M1 : matrix([0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 2, 0],
                            [0, 0, 0, 2]);
                                   [ 0  1  0  0 ]
                                   [            ]
                                   [ 0  0  0  0 ]
          (%o1)                    [            ]
                                   [ 0  0  2  0 ]
                                   [            ]
                                   [ 0  0  0  2 ]
          (%i2) [vals, vecs] : eigenvectors (M1);
          (%o2) [[[0, 2], [2, 2]], [[[1, 0, 0, 0]],
                                             [[0, 0, 1, 0], [0, 0, 0, 1]]]]
          (%i3) for i thru length (vals[1]) do disp (val[i] = vals[1][i],
            mult[i] = vals[2][i], vec[i] = vecs[i]);
                                      val  = 0
                                         1

                                      mult  = 2
                                          1

                                vec  = [[1, 0, 0, 0]]
                                   1

                                      val  = 2
                                         2

                                      mult  = 2
                                          2

                         vec  = [[0, 0, 1, 0], [0, 0, 0, 1]]
                            2

          (%o3)                         done

 -- Funktion: ematrix (<m>, <n>, <x>, <i>, <j>)

     Gibt eine <m> 'x' <n>-Matrix zurück, deren Elemente den Wert 0
     haben, bis auf das Element '[<i>, <j>]', das den Wert <x> hat.

 -- Funktion: entermatrix (<m>, <n>)

     Gibt eine <m> 'x' <n>-Matrix zurück, die von der Konsole eingelesen
     wird.

     Ist <n> gleich <m>, fragt Maxima nach dem Typ der Matrix.  Folgende
     Typen können angegeben werden: diagonal, symmetric, antisymmetric
     oder allgemein.  Dannach werden die einzelnen Elemente der Matrix
     abgefragt.

     Sind <n> und <m> voneinander verschieden, fragt Maxima nach jedem
     Element der Matrix.

     Die Elemente können beliebige Ausdrücke sein, die ausgewertet
     werden.  'entermatrix' wertet die Argumente aus.

     Beispiel:

          (%i1) n: 3$
          (%i2) m: entermatrix (n, n)$

          Is the matrix  1. Diagonal  2. Symmetric  3. Antisymmetric
          4. General
          Answer 1, 2, 3 or 4 :
          1$
          Row 1 Column 1:
          (a+b)^n$
          Row 2 Column 2:
          (a+b)^(n+1)$
          Row 3 Column 3:
          (a+b)^(n+2)$

          Matrix entered.
          (%i3) m;
                          [        3                     ]
                          [ (b + a)      0         0     ]
                          [                              ]
          (%o3)           [                  4           ]
                          [    0      (b + a)      0     ]
                          [                              ]
                          [                            5 ]
                          [    0         0      (b + a)  ]

 -- Funktion: express (<expr>)

     Expandiert Differentialoperatoren in einem Ausdruck in partielle
     Ableitungen.  'express' erkennt die Operatoren 'grad', 'div',
     'curl', 'laplacian' und das Kreuzprodukt '~'.

     Enthält die Rückgabe Substantivformen von Ableitungen, können diese
     mit der Funktion 'ev' und den Auswertungsschaltern 'nouns' oder
     'diff' ausgewertet werden.

     Mit dem Kommando 'load(vect)' wird die Funktion geladen.

     Beispiele:

          (%i1) load ("vect")$
          (%i2) grad (x^2 + y^2 + z^2);
                                        2    2    2
          (%o2)                  grad (z  + y  + x )
          (%i3) express (%);
                 d    2    2    2   d    2    2    2   d    2    2    2
          (%o3) [-- (z  + y  + x ), -- (z  + y  + x ), -- (z  + y  + x )]
                 dx                 dy                 dz
          (%i4) ev (%, diff);
          (%o4)                    [2 x, 2 y, 2 z]
          (%i5) div ([x^2, y^2, z^2]);
                                        2   2   2
          (%o5)                   div [x , y , z ]
          (%i6) express (%);
                             d    2    d    2    d    2
          (%o6)              -- (z ) + -- (y ) + -- (x )
                             dz        dy        dx
          (%i7) ev (%, diff);
          (%o7)                    2 z + 2 y + 2 x
          (%i8) curl ([x^2, y^2, z^2]);
                                         2   2   2
          (%o8)                   curl [x , y , z ]
          (%i9) express (%);
                 d    2    d    2   d    2    d    2   d    2    d    2
          (%o9) [-- (z ) - -- (y ), -- (x ) - -- (z ), -- (y ) - -- (x )]
                 dy        dz       dz        dx       dx        dy
          (%i10) ev (%, diff);
          (%o10)                      [0, 0, 0]
          (%i11) laplacian (x^2 * y^2 * z^2);
                                            2  2  2
          (%o11)                laplacian (x  y  z )
          (%i12) express (%);
                   2                2                2
                  d     2  2  2    d     2  2  2    d     2  2  2
          (%o12)  --- (x  y  z ) + --- (x  y  z ) + --- (x  y  z )
                    2                2                2
                  dz               dy               dx
          (%i13) ev (%, diff);
                                2  2      2  2      2  2
          (%o13)             2 y  z  + 2 x  z  + 2 x  y
          (%i14) [a, b, c] ~ [x, y, z];
          (%o14)                [a, b, c] ~ [x, y, z]
          (%i15) express (%);
          (%o15)          [b z - c y, c x - a z, a y - b x]

 -- Funktion: genmatrix (<a>, <i_2>, <j_2>, <i_1>, <j_1>)
 -- Funktion: genmatrix (<a>, <i_2>, <j_2>, <i_1>)
 -- Funktion: genmatrix (<a>, <i_2>, <j_2>)

     Generiert eine Matrix aus einem Array <a>.  Das erste Element der
     Matrix ist der Wert '<a>[<i_1>,<j_1>]' und das letzte Element der
     Matrix ist '<a>[<i_2>,<j_2>]'.  <a> muss ein deklariertes Array
     sein, dass mit der Funktion 'array' definiert wurde.  Weiterhin
     kann <a> ein undeklariertes Array, eine Array-Funktion oder ein
     lambda-Ausdruck mit zwei Argumenten sein.

     Wird <j_1> nicht angegeben, nimmt Maxima an, das der Wert gleich
     <i_1> ist.  Werden beide Argumente <j_1> und <i_1> nicht angegeben,
     werden die Werte zu 1 angenommen.

     Ist eines der Elemente '[i,j]' des Arrays nicht definiert, enthält
     die Matrix den symbolischen Wert '<a>[i,j]'.

     Beispiele:

          (%i1) h [i, j] := 1 / (i + j - 1);
                                              1
          (%o1)                  h     := ---------
                                  i, j    i + j - 1
          (%i2) genmatrix (h, 3, 3);
                                     [    1  1 ]
                                     [ 1  -  - ]
                                     [    2  3 ]
                                     [         ]
                                     [ 1  1  1 ]
          (%o2)                      [ -  -  - ]
                                     [ 2  3  4 ]
                                     [         ]
                                     [ 1  1  1 ]
                                     [ -  -  - ]
                                     [ 3  4  5 ]
          (%i3) array (a, fixnum, 2, 2);
          (%o3)                           a
          (%i4) a [1, 1] : %e;
          (%o4)                          %e
          (%i5) a [2, 2] : %pi;
          (%o5)                          %pi
          (%i6) genmatrix (a, 2, 2);
                                     [ %e   0  ]
          (%o6)                      [         ]
                                     [ 0   %pi ]
          (%i7) genmatrix (lambda ([i, j], j - i), 3, 3);
                                   [  0    1   2 ]
                                   [             ]
          (%o7)                    [ - 1   0   1 ]
                                   [             ]
                                   [ - 2  - 1  0 ]
          (%i8) genmatrix (B, 2, 2);
                                  [ B      B     ]
                                  [  1, 1   1, 2 ]
          (%o8)                   [              ]
                                  [ B      B     ]
                                  [  2, 1   2, 2 ]

 -- Funktion: gramschmidt (<x>)
 -- Funktion: gramschmidt (<x>, <F>)

     Wendet das Gram-Schmidtsche Orthogonalisierungsverfahren auf das
     Argument <x> an.  <x> ist eine Matrix oder eine Liste mit Listen
     für die Spalten.  Das Argument <x> wird von 'gramschmidt' nicht
     verändert.  <F> bezeichnet eine Funktion, die als Skalarprodukt für
     das Verfahren verwendet wird.  Wird <F> nicht angegeben, wird die
     Funktion 'innerproduct' für das Skalarprodukt angewendet.

     Ist <x> eine Matrix, wird der Algorithmus auf die Zeilen der Matrix
     angewendet.  Ist <x> eine Liste mit Listen, wird der Algorithmus
     auf die Teillisten angewendet, die jeweils die gleiche Anzahl an
     Elementen haben müssen.

     Jede Stufe des Verfahrens ruft die Funktion 'factor' auf, um die
     Zwischenergebnisse zu vereinfachen.  Dadurch kann das Ergebnis
     faktorisierte ganze Zahlen enthalten.

     Das Kommando 'load(eigen)' lädt die Funktion.

     Beispiele:

     Das Gram-Schmidtsche Orthogonalisierungsverfahren mit
     'innerproduct' als Skalarprodukt.

          (%i1) load (eigen)$
          (%i2) x: matrix ([1, 2, 3], [9, 18, 30], [12, 48, 60]);
                                   [ 1   2   3  ]
                                   [            ]
          (%o2)                    [ 9   18  30 ]
                                   [            ]
                                   [ 12  48  60 ]
          (%i3) y: gramschmidt (x);
                                 2      2            4     3
                                3      3   3 5      2  3  2  3
          (%o3)  [[1, 2, 3], [- ---, - --, ---], [- ----, ----, 0]]
                                2 7    7   2 7       5     5
          (%i4) map (innerproduct, [y[1], y[2], y[3]], [y[2], y[3], y[1]]);
          (%o4)                       [0, 0, 0]

     Das Gram-Schmidtsche Orthogonalisierungsverfahren mit einer
     selbstdefinierten Funktion für das Skalarprodukt.

          (%i1) load (eigen)$
          (%i2) ip (f, g) := integrate (f * g, u, a, b);
          (%o2)          ip(f, g) := integrate(f g, u, a, b)
          (%i3) y : gramschmidt([1, sin(u), cos(u)], ip), a=-%pi/2, b=%pi/2;
                                         %pi cos(u) - 2
          (%o3)              [1, sin(u), --------------]
                                              %pi
          (%i4) map(ip,[y[1],y[2],y[3]],[y[2],y[3],y[1]]), a=-%pi/2, b=%pi/2;
          (%o4)                       [0, 0, 0]

 -- Funktion: ident (<n>)

     Gibt eine <n> 'x' <n>-Einheitsmatrix zurück.

 -- Funktion: innerproduct (<x>, <y>)
 -- Funktion: inprod (<x>, <y>)

     Gibt das Skalarprodukt der Argumente <x> und <y> zurück.  Die
     Argument können Listen oder 1-spaltige oder 1-reihige Matrizen
     sein.  Das Skalarprodukt wird als 'conjugate(x) . y' berechnet,
     wobei '.' der Operator der nicht-kommutativen Multiplikation ist.

     Das Kommando 'load(eigen)' lädt die Funktion.

     'inprod' ist ein Alias-Name der Funktion 'innerproduct'.

 -- Funktion: invert (<M>)

     Gibt die inverse Matrix der Matrix <M> zurück.  Die inverse Matrix
     wird mittels der Adjunkten Matrix berechnet.

     Mit dieser Methode kann die inverse Matrix auch für große
     Gleitkommazahlen sowie Polynomme als Matrixelemente berechnet
     werden.

     Die Kofaktoren werden mit der Funktion 'determinant' berechnet.
     Hat die Optionsvariable 'ratmx' den Wert 'true', wird die inverse
     Matrix daher ohne einen Wechsel der Darstellung berechnet.

     Die implementierte Methode ist jedoch ineffizient für große
     Matrizen.

     Hat die Optionsvariable 'detout' den Wert 'true', wird die
     Determinante als Faktor aus der Matrix herausgezogen.

     Die Elemente der inversen Matrix werden nicht automatisch
     expandiert.  Hat <M> Polynome als Elemente, hat das Ergebnis
     möglicherweise mit dem Kommando 'expand(invert(m)), detout' eine
     einfachere Form.  Mit der Funktion 'multthru' die Determinate in
     die Matrix hereinmultipliziert werden.  Die inverse Matrix kann
     auch folgendermaßen berechnet werden:

          expand (adjoint (m)) / expand (determinant (m))
          invert (m) := adjoint (m) / determinant (m)

     Siehe auch den Operator '^^' der nicht-kommutativen Exponentiation
     für eine andere Methode zur Berechnung der inversen Matrix.

 -- Optionsvariable: lmxchar
     Standardwert: '['

     'lmxchar' ist das Zeichen, das für die linke Seite einer Matrix
     ausgegeben wird.  Siehe auch 'rmxchar'.

     Beispiel:

          (%i1) lmxchar: "|"$
          (%i2) matrix ([a, b, c], [d, e, f], [g, h, i]);
                                     | a  b  c ]
                                     |         ]
          (%o2)                      | d  e  f ]
                                     |         ]
                                     | g  h  i ]

 -- Funktion: matrix (<row_1>, ..., <row_n>)

     Gibt eine Matrix mit den Spalten <row_1>, ..., <row_n> zurück.
     Jede Spalte ist eine Liste mit Asudrücken.  Alle Spalten müssen die
     gleiche Länge haben.

     Die Addition '+', Subtraktion '-', Multiplikation '*' und Division
     '/' werden elementweise ausgeführt, wenn die Argumente zwei
     Matrizen, ein Skalar und eine Matrix oder eine Matrix und ein
     Skalar sind.  Die Exponentiation '^' wird elementweise ausgeführt,
     wenn die Argumente ein Skalar und eine Matrix oder umgekehrt sind.

     Die nichtkommutatie Multiplikation von Matrizen wird mit dem
     Operator '.' ausgeführt.  Der entsprechende Operator für die
     nichtkommutative Exponentiation ist '^^'.  Für eine Matrix '<A>'
     ist '<A> . <A> = <A>^^2'.  '<A>^^-1' ist die inverse Matrix, falls
     diese existiert.

     Folgende Schalter kontrollieren die Vereinfachung von Ausdrücken,
     welche die nichtkommutative Multiplikation und Matrizen enthalten:

     'doallmxops', 'domxexpt', 'domxmxops', 'doscmxops' und
     'doscmxplus'.

     Weitere Optionsvariablen für Matrizen sind:

     'lmxchar', 'rmxchar', 'ratmx', 'listarith', 'detout',
     'scalarmatrix' und 'sparse'.

     Folgende Funktionen akzeptieren Matrizen als ein Argument oder
     haben eine Matrix als Rückgabewert:

     'eigenvalues', 'eigenvectors', 'determinant', 'charpoly',
     'genmatrix', 'addcol', 'addrow', 'copymatrix', 'transpose',
     'echelon' and 'rank'.

     Beispiele:

     Konstruiere eine Matrix mit Listen.

          (%i1) x: matrix ([17, 3], [-8, 11]);
                                     [ 17   3  ]
          (%o1)                      [         ]
                                     [ - 8  11 ]
          (%i2) y: matrix ([%pi, %e], [a, b]);
                                     [ %pi  %e ]
          (%o2)                      [         ]
                                     [  a   b  ]

     Elementweise Addition zweier Matrizen.

          (%i3) x + y;
                                [ %pi + 17  %e + 3 ]
          (%o3)                 [                  ]
                                [  a - 8    b + 11 ]

     Elementweise Subtraktion zweier Matrizen.

          (%i4) x - y;
                                [ 17 - %pi  3 - %e ]
          (%o4)                 [                  ]
                                [ - a - 8   11 - b ]

     Elementweise Multiplikation zweier Matrizen.

          (%i5) x * y;
                                  [ 17 %pi  3 %e ]
          (%o5)                   [              ]
                                  [ - 8 a   11 b ]

     Elementweise Division zweier Matrizen.

          (%i6) x / y;
                                  [ 17       - 1 ]
                                  [ ---  3 %e    ]
                                  [ %pi          ]
          (%o6)                   [              ]
                                  [   8    11    ]
                                  [ - -    --    ]
                                  [   a    b     ]

     Elementweise Exponentiation einer Matrix mit einem Skalar.

          (%i7) x ^ 3;
                                   [ 4913    27  ]
          (%o7)                    [             ]
                                   [ - 512  1331 ]

     Elementweise Exponentiation eines Skalars mit einer Matrix.

          (%i8) exp(y);
                                   [   %pi    %e ]
                                   [ %e     %e   ]
          (%o8)                    [             ]
                                   [    a     b  ]
                                   [  %e    %e   ]

     Die Exponentiation zweier Matrizen wird nicht elementweise
     ausgeführt.

          (%i9) x ^ y;
                                          [ %pi  %e ]
                                          [         ]
                                          [  a   b  ]
                               [ 17   3  ]
          (%o9)                [         ]
                               [ - 8  11 ]

     Nichtkommutative Multiplikation zweier Matrizen.

          (%i10) x . y;
                            [ 3 a + 17 %pi  3 b + 17 %e ]
          (%o10)            [                           ]
                            [ 11 a - 8 %pi  11 b - 8 %e ]
          (%i11) y . x;
                          [ 17 %pi - 8 %e  3 %pi + 11 %e ]
          (%o11)          [                              ]
                          [  17 a - 8 b     11 b + 3 a   ]

     Nichtkommutative Exponentiation einer Matrix.  Ist die Basis ein
     Skalar wird die Exponentiation elementweise ausgeführt.  Daher
     haben die Operationen '^^' und '^' für diesen Fall dasselbe
     Ergebnis.

          (%i12) x ^^ 3;
                                  [  3833   1719 ]
          (%o12)                  [              ]
                                  [ - 4584  395  ]
          (%i13) %e ^^ y;
                                   [   %pi    %e ]
                                   [ %e     %e   ]
          (%o13)                   [             ]
                                   [    a     b  ]
                                   [  %e    %e   ]

     Berechnung der inversen Matrix mit 'x^^-1'.

          (%i14) x ^^ -1;
                                   [ 11      3  ]
                                   [ ---  - --- ]
                                   [ 211    211 ]
          (%o14)                   [            ]
                                   [  8    17   ]
                                   [ ---   ---  ]
                                   [ 211   211  ]
          (%i15) x . (x ^^ -1);
                                      [ 1  0 ]
          (%o15)                      [      ]
                                      [ 0  1 ]

 -- Funktion: matrixmap (<f>, <M>)

     Gibt eine Matrix mit den Elementen '[i,j]' zurück, die mit
     '<f>(<M>[i,j])' berechnet werden.

     Siehe auch 'map', 'fullmap', 'fullmapl', and 'apply'.

 -- Funktion: matrixp (<expr>)

     Gibt 'true' zurück, wenn <expr> eine Matrix ist.  Ansonsten wird
     'false' zurückgegeben.

 -- Optionsvariable: matrix_element_add
     Standardwert: '+'

     'matrix_element_add' enthält die Operation für die Ausführung der
     Addition von Matrizen.  Der Optionsvariablen 'matrix_element_add'
     kann ein N-Ary-Operator zugewiesen werden.  Der zugewiesene Wert
     kann der Name eines Operators, einer Funktion oder ein
     Lambda-Ausdruck sein.

     Siehe auch 'matrix_element_mult' und 'matrix_element_transpose'.

     Beispiele:

          (%i1) matrix_element_add: "*"$
          (%i2) matrix_element_mult: "^"$
          (%i3) aa: matrix ([a, b, c], [d, e, f]);
                                     [ a  b  c ]
          (%o3)                      [         ]
                                     [ d  e  f ]
          (%i4) bb: matrix ([u, v, w], [x, y, z]);
                                     [ u  v  w ]
          (%o4)                      [         ]
                                     [ x  y  z ]
          (%i5) aa . transpose (bb);
                               [  u  v  w   x  y  z ]
                               [ a  b  c   a  b  c  ]
          (%o5)                [                    ]
                               [  u  v  w   x  y  z ]
                               [ d  e  f   d  e  f  ]

 -- Optionsvariable: matrix_element_mult
     Standardwert: '*'

     'matrix_element_mult' enthält die Operation für die Ausführung der
     Multiplikation von Matrizen.  Der Optionsvariablen
     'matrix_element_mult' kann ein binärer Operator zugewiesen werden.
     Der zugewiesene Wert kann der Name eines Operators, einer Funktion
     oder ein Lambda-Ausdruck sein.

     Der nichtkommutative Operator '.' kann eine sinnvolle Alternative
     sein.

     Siehe auch 'matrix_element_add' und 'matrix_element_transpose'.

     Beispiele:

          (%i1) matrix_element_add: lambda ([[x]], sqrt (apply ("+", x)))$
          (%i2) matrix_element_mult: lambda ([x, y], (x - y)^2)$
          (%i3) [a, b, c] . [x, y, z];
                                    2          2          2
          (%o3)         sqrt((c - z)  + (b - y)  + (a - x) )
          (%i4) aa: matrix ([a, b, c], [d, e, f]);
                                     [ a  b  c ]
          (%o4)                      [         ]
                                     [ d  e  f ]
          (%i5) bb: matrix ([u, v, w], [x, y, z]);
                                     [ u  v  w ]
          (%o5)                      [         ]
                                     [ x  y  z ]
          (%i6) aa . transpose (bb);
                         [             2          2          2  ]
                         [ sqrt((c - w)  + (b - v)  + (a - u) ) ]
          (%o6)  Col 1 = [                                      ]
                         [             2          2          2  ]
                         [ sqrt((f - w)  + (e - v)  + (d - u) ) ]

                                   [             2          2          2  ]
                                   [ sqrt((c - z)  + (b - y)  + (a - x) ) ]
                           Col 2 = [                                      ]
                                   [             2          2          2  ]
                                   [ sqrt((f - z)  + (e - y)  + (d - x) ) ]

 -- Optionsvariable: matrix_element_transpose
     Standardwert: 'false'

     'matrix_element_transpose' enthält die Operation für die Ausführung
     der Transponierung einer Matrix.  Der Optionsvariablen
     'matrix_element_mult' kann ein unärer Operator zugewiesen werden.
     Der zugewiesene Wert kann der Name eines Operators, einer Funktion
     oder ein Lambda-Ausdruck sein.

     Hat 'matrix_element_transpose' den Wert 'transpose', wird die
     Funktion 'transpose' auf jedes Element der Matrix angewendet.  Hat
     'matrix_element_transpose' den Wert 'nonscalars', wird die Funktion
     'transpose' auf nichtskalare Elemente der Matrix angewendet.  Ist
     eines der Elemente ein Atom, muss in diesem Fall das Atom als
     'nonscalar' deklariert sein.

     Mit dem Standardwert 'false' wird keine Operation angewendet.

     Siehe auch 'matrix_element_add' und 'matrix_element_mult'.

     Beispiele:

          (%i1) declare (a, nonscalar)$
          (%i2) transpose ([a, b]);
                                  [ transpose(a) ]
          (%o2)                   [              ]
                                  [      b       ]
          (%i3) matrix_element_transpose: nonscalars$
          (%i4) transpose ([a, b]);
                                  [ transpose(a) ]
          (%o4)                   [              ]
                                  [      b       ]
          (%i5) matrix_element_transpose: transpose$
          (%i6) transpose ([a, b]);
                                  [ transpose(a) ]
          (%o6)                   [              ]
                                  [ transpose(b) ]
          (%i7) matrix_element_transpose: lambda ([x], realpart(x)
                - %i*imagpart(x))$
          (%i8) m: matrix ([1 + 5*%i, 3 - 2*%i], [7*%i, 11]);
                               [ 5 %i + 1  3 - 2 %i ]
          (%o8)                [                    ]
                               [   7 %i       11    ]
          (%i9) transpose (m);
                                [ 1 - 5 %i  - 7 %i ]
          (%o9)                 [                  ]
                                [ 2 %i + 3    11   ]

 -- Funktion: mattrace (<M>)

     Gibt die Spur einer quadratischen Matrix <M> zurück.

 -- Funktion: minor (<M>, <i>, <j>)

     Gibt den Minor zu <i>, <j> der Matrix <M> zurück.  Die Matrix
     entsteht durch Streichen der <i>-ten Spalte und <j>-ten Zeile.

 -- Funktion: ncharpoly (<M>, <x>)

     Gibt das charakteristische Polynom der Matrix <M> für die Variable
     <x> zurück.  Diese Funktion ist eine Alternative zur Funktion
     'charpoly'.

     Der Algorithmus von 'ncharpoly' ist vorteilhaft gegenüber
     'charpoly', wenn große und dünn besetzte Matrizen vorliegen.  Das
     Kommando 'load(nchrpl' lädt die Funktion.

 -- Funktion: newdet (<M>, <n>)

     Berechnet die Determinate der Matrix oder eines Arrays <M> mit dem
     Johnson-Gentleman-Algorithmus.  Das Argument <n> ist die Ordnung.
     Für eine Matrix ist <n> ein optionales Argument.

 -- Funktion: permanent (<M>, <n>)

     Berechnet die Permanente der Matrix <M>.  Die Permanente ist
     ähnlich der Determinate, aber es fehlen die Vorzeichenwechsel.

 -- Funktion: rank (<M>)

     Berechnet den Rang der Matrix <M>.

     <rank> kann ein falsches Ergebnis geben, wenn ein Element
     äquivalent zu Null ist, dies aber nicht von Maxima festgestellt
     werden kann.

 -- Funktion: potential (<givengradient>)

     The calculation makes use of the global variable
     'potentialzeroloc[0]' which must be 'nonlist' or of the form

          [indeterminatej=expressionj, indeterminatek=expressionk, ...]

     the former being equivalent to the nonlist expression for all
     right-hand sides in the latter.  The indicated right-hand sides are
     used as the lower limit of integration.  The success of the
     integrations may depend upon their values and order.
     'potentialzeroloc' is initially set to 0.

 -- Optionsvariable: ratmx
     Standardwert: 'false'

     Hat 'ratmx' den Wert 'false', werden die Berechnung einer
     Determinante sowie die Operationen der Addition, Subtraktion und
     Multiplikation in der allgemeinen Darstellung ausgeführt.  Das
     Ergebnis ist wieder eine allgemeine Darstellung.

     Hat 'ratmx' den Wert 'true', werden die oben genannten Operationen
     in einer CRE-Darstellung ausgeführt un das Ergebnis ist in einer
     CRE-Darstellung.

 -- Optionsvariable: rmxchar
     Standardwert: ']'

     'rmxchar' ist das Zeichen, das für die rechte Seite einer Matrix
     ausgegeben wird.  Siehe auch 'lmxchar'.

 -- Funktion: row (<M>, <i>)

     Gibt die <i>-te Spalte der Matrix <M> zurück.  Der Rückgabewert ist
     eine Matrix.

 -- Optionsvariable: scalarmatrixp
     Standardwert: 'true'

     Hat 'scalarmatrixp' den Wert 'true', dann werden 1 x 1-Matrizen,
     die als Ergebnis einer nicht-kommutativen Multiplikation auftreten,
     zu einem Skalar vereinfacht.

     Hat 'scalarmatrixp' den Wert 'all', dann werden alle 1 x 1-Matrizen
     zu einem Skalar vereinfacht.

     Hat 'scalarmatrixp' den Wert 'false', werden 1 x 1-Matrizen nicht
     zu einem Skalar vereinfacht.

 -- Funktion: scalefactors (<coordinatetransform>)

     Here coordinatetransform evaluates to the form [[expression1,
     expression2, ...], indeterminate1, indeterminat2, ...], where
     indeterminate1, indeterminate2, etc.  are the curvilinear
     coordinate variables and where a set of rectangular Cartesian
     components is given in terms of the curvilinear coordinates by
     [expression1, expression2, ...].  'coordinates' is set to the
     vector [indeterminate1, indeterminate2, ...], and 'dimension' is
     set to the length of this vector.  SF[1], SF[2], ..., SF[DIMENSION]
     are set to the coordinate scale factors, and 'sfprod' is set to the
     product of these scale factors.  Initially, 'coordinates' is [X, Y,
     Z], 'dimension' is 3, and SF[1]=SF[2]=SF[3]=SFPROD=1, corresponding
     to 3-dimensional rectangular Cartesian coordinates.  To expand an
     expression into physical components in the current coordinate
     system, there is a function with usage of the form

 -- Funktion: setelmx (<x>, <i>, <j>, <M>)

     Weist <x> dem Matrixelement '[<i>,<j>]' zu und gibt die
     modifizierte Matrix zurück.

     '<M>[<i>, <j>]: <x>' hat denselben Effekt.  In diesem Fall wird
     jedoch der Wert <x> zurückgeben und nicht die Matrix.

 -- Funktion: similaritytransform (<M>)
 -- Funktion: simtran (<M>)

     'similaritytransform' computes a similarity transform of the matrix
     'M'.  It returns a list which is the output of the
     'uniteigenvectors' command.  In addition if the flag
     'nondiagonalizable' is 'false' two global matrices 'leftmatrix' and
     'rightmatrix' are computed.  These matrices have the property that
     'leftmatrix . <M> . rightmatrix' is a diagonal matrix with the
     eigenvalues of <M> on the diagonal.  If 'nondiagonalizable' is
     'true' the left and right matrices are not computed.

     If the flag 'hermitianmatrix' is 'true' then 'leftmatrix' is the
     complex conjugate of the transpose of 'rightmatrix'.  Otherwise
     'leftmatrix' is the inverse of 'rightmatrix'.

     'rightmatrix' is the matrix the columns of which are the unit
     eigenvectors of <M>.  The other flags (see 'eigenvalues' and
     'eigenvectors') have the same effects since 'similaritytransform'
     calls the other functions in the package in order to be able to
     form 'rightmatrix'.

     'load ("eigen")' loads this function.

     'simtran' is a synonym for 'similaritytransform'.

 -- Optionsvariable: sparse
     Standardwert: 'false'

     Haben 'sparse' und 'ratmx' den Wert 'true', verwendet die Funktion
     'determinant' einen speziellen Algorithmus für dünn besetzte
     Matrizen, um die Determinante einer Matrix zu berechnen.

 -- Funktion: submatrix (<i_1>, ..., <i_m>, <M>, <j_1>, ..., <j_n>)
 -- Funktion: submatrix (<i_1>, ..., <i_m>, <M>)
 -- Funktion: submatrix (<M>, <j_1>, ..., <j_n>)

     Gibt eine Kopie der Matrix <M> zurück, in der die Zeilen <i_1>,
     ..., <i_m> und Spalten <j_1>, ..., <j_n> nicht enthalten sind.

 -- Funktion: transpose (<M>)

     Gibt die Transponierte der Matrix <M> zurück.

     Ist <M> eine Matrix, ist das Ergebnis eine Matrix <N> mit den
     Elementen 'N[i,j] = M[j,i]'.

     Ist <M> eine Liste, ist die Rückgabe eine Matrix <N> mit
     'length(M)' Spalten und einer Zeile.  Die Elemente sind 'N[i,1] =
     M[i]'.

     Ansonsten wird eine Substantivform ''transpose(<M>)' zurückgegeben.

 -- Funktion: triangularize (<M>)

     Gibt die obere Dreiecksmatrix für die Matrix 'M' zurück, wie sie
     mit dem Gaußschen Eliminationsverfahren berechnet wird.  Die
     Dreiecksmatrix entspricht der Rückgabe der Funktion 'echelon' mit
     dem Unterschied, dass die Elemente auf der Diagonalen nicht zu 1
     normalisiert sind.

     Mit den Funktionen 'lu_factor' und 'cholesky' kann ebenfalls eine
     Matrix in die Dreiecksform transformiert werden.

     Beispiel:

          (%i1) M: matrix ([3, 7, aa, bb], [-1, 8, 5, 2], [9, 2, 11, 4]);
                                 [  3   7  aa  bb ]
                                 [                ]
          (%o1)                  [ - 1  8  5   2  ]
                                 [                ]
                                 [  9   2  11  4  ]
          (%i2) triangularize (M);
                       [ - 1   8         5            2      ]
                       [                                     ]
          (%o2)        [  0   - 74     - 56         - 22     ]
                       [                                     ]
                       [  0    0    626 - 74 aa  238 - 74 bb ]

 -- Funktion: uniteigenvectors (<M>)
 -- Funktion: ueivects (<M>)

     Berechnet die Einheitsvektoren der Matrix <M>.  Die Rückgabe ist
     eine Liste, die zwei weitere Listen enthält.  Die erste Liste
     enthält die Eigenwerte der Matrix <M> und deren Multiplizitäten.
     Die zweite Liste enthält die Einheitsvektoren.

     Ansonsten entspricht 'uniteigenvectors' der Funktion
     'eigenvectors'.

     Das Kommando 'load(eigen)' lädt die Funktion.

     'ueivects' ist ein Alias-Name der Funkion 'uniteigenvectors'.

 -- Funktion: unitvector (<x>)
 -- Funktion: uvect (<x>)

     Gibt den Einheitsvektor <x>/norm(<x>) zurück.

     Das Kommando 'load(eigen)' lädt die Funktion.

     'uvect' ist ein Alias-Name der Funktion 'unitvector'.

 -- Funktion: vectorpotential (<givencurl>)

     Returns the vector potential of a given curl vector, in the current
     coordinate system.  'potentialzeroloc' has a similar role as for
     'potential', but the order of the left-hand sides of the equations
     must be a cyclic permutation of the coordinate variables.

 -- Funktion: vectorsimp (<expr>)

     Applies simplifications and expansions according to the following
     global flags:

     expandall         expanddot             expanddotplus
     expandcross       expandcrossplus       expandcrosscross
     expandgrad        expandgradplus        expandgradprod
     expanddiv         expanddivplus         expanddivprod
     expandcurl        expandcurlplus        expandcurlcurl
     expandlaplacian   expandlaplacianplus   expandlaplacianprod

     All these flags have default value 'false'.  The 'plus' suffix
     refers to employing additivity or distributivity.  The 'prod'
     suffix refers to the expansion for an operand that is any kind of
     product.

     'expandcrosscross'
          Simplifies 'p ~ (q ~ r)' to '(p . r)*q - (p . q)*r'.

     'expandcurlcurl'
          Simplifies 'curl curl p' to 'grad div p + div grad p'.

     'expandlaplaciantodivgrad'
          Simplifies 'laplacian p' to 'div grad p'.

     'expandcross'
          Enables 'expandcrossplus' and 'expandcrosscross'.

     'expandplus'
          Enables 'expanddotplus', 'expandcrossplus', 'expandgradplus',
          'expanddivplus', 'expandcurlplus', and 'expandlaplacianplus'.

     'expandprod'
          Enables 'expandgradprod', 'expanddivprod', and
          'expandlaplacianprod'.

     These flags have all been declared 'evflag'.

 -- Optionsvariable: vect_cross
     Standardwert: 'false'

     Hat 'vect_cross' den Wert 'true', werden Ausdrücke, die die
     Ableitung eines Kreuzproduktes enthalten, vereinfacht.

     Beispiel:

          (%i1) load(vect)$

          (%i2) vect_cross:false;
          (%o2)                         false
          (%i3) diff(f(x)~g(x),x);
                                  d
          (%o3)                   -- (f(x) ~ g(x))
                                  dx
          (%i4) vect_cross:true;
          (%o4)                         true
          (%i5) diff(f(x)~g(x),x);
                               d                    d
          (%o5)        f(x) ~ (-- (g(x))) - g(x) ~ (-- (f(x)))
                               dx                   dx

 -- Funktion: zeromatrix (<m>, <n>)

     Gibt eine <m> x <n>-Matrix zurück, deren Elemente alle Null sind.


File: maxima.info,  Node: Tensoren,  Next: Zahlentheorie,  Prev: Lineare Algebra,  Up: Top

20 Tensoren
***********

* Menu:

* Tensorpakete in Maxima::
* Paket itensor::
* Paket ctensor::
* Paket atensor::


File: maxima.info,  Node: Tensorpakete in Maxima,  Next: Paket itensor,  Prev: Tensoren,  Up: Tensoren

20.1 Tensorpakete in Maxima
===========================

Maxima hat drei verschiedene Pakete, um mit Tensoren zu rechnen.  Das
Paket 'ctensor' implementiert das Rechnen mit Tensoren in der
Koordinatendarstellung und das Paket 'itensor' das Rechnen in einer
Indexnotation.  Das Paket 'atensor' erlaubt die algebraische
Manipulation von Tensoren in verschiedenen Algebren.

Beim Rechnen in einer Koordinatendarstellung mit dem Paket 'ctensor'
werden Tensoren als Arrays oder Matrizen dargestellt.  Operationen mit
Tensoren wie die Tensorverjüngung oder die kovariante Ableitung werden
ausgeführt als Operationen mit den Komponenten des Tensors, die in einem
Array oder einer Matrix gespeichert sind.

Beim Rechnen in der Indexnotation mit dem Paket 'itensor' werden
Tensoren als Funktionen ihrer kovarianten und kontravarianten Indizes
sowie den Ableitungen nach den Komponenten dargestellt.  Operationen wie
die Tensorverjüngung oder die kovariante Ableitung werden ausgeführt, in
dem die Indizes manipuliert werden.

Die beiden genannten Pakete 'itensor' und 'ctensor' für die Behandlung
von mathematischen Problemen im Zusammenhang mit der Riemannschen
Geometrie haben verschiedene Vor- und Nachteile, die sich erst anhand
des zu behandelnden Problems und dessen Schwierigkeitsgrad zeigen.
Folgenden Eigenschaften der beiden Implementierungen sollten beachtet
werden:

Die Darstellung von Tensoren und Tensoroperationen in einer expliziten
Koordinatendarstellung vereinfacht die Nutzung des Paketes 'ctensor'.
Die Spezifikation der Metrik und die Ableitung von Tensoren sowie von
Invarianten ist unkompliziert.  Trotz Maximas Methoden für die
Vereinfachung von Ausdrücken kann jedoch eine komplexe Metrik mit
komplizierten funktionalen Abhängigkeiten der Koordinaten leicht zu sehr
großen Ausdrücken führen, die die Struktur eines Ergebnisses verbergen.
Weiterhin können Rechnungen zu sehr großen Zwischenergebnisse führen,
die zu einem Programmabbruch führen, bevor die Rechnung beendet werden
kann.  Jedoch kann der Nutzer mit einiger Erfahrung viele dieser
Probleme vermeiden.

Aufgrund der besonderen Weise, wie Tensoren und Tensoroperationen als
symbolische Operationen ihrer Indizes dargestellt werden, können
Ausdrücke, die in einer Koordinatendarstellung sehr unhandlich sind, mit
Hilfe spezieller Routinen für symmetrische Objekte in 'itensor' manchmal
erheblich vereinfacht werden.  Auf diese Weise kann die Struktur großer
Ausdrücke transparenter sein.  Auf der anderen Seite kann die
Spezifikation einer Metrik, die Definition von Funktionen und die
Auswertung von abgeleiteten indizierten Objekten für den Nutzer
schwierig sein.

Mit dem Paket 'itensor' können Ableitungen nach einer indizierten
Variablen ausgeführt werden, wodurch es möglich ist, 'itensor' auch für
Probleme im Zusammenhang mit dem Lagrange- oder Hamiltonian-Formalismus
einzusetzen.  Da es möglich ist, die Lagrangeschen Feldgleichungen nach
einer indizierten Variablen abzuleiten, können zum Beispiel die
Euler-Lagrange-Gleichungen in einer Indexnotation aufgestellt werden.
Werden die Gleichungen mit der Funktion 'ic_convert' in eine
Komponentendarstellung für das Paket 'ctensor' transformiert, können die
Feldgleichungen in einer bestimmten Koordinatendarstellung gelöst
werden.  Siehe dazu die ausführlichen Beispiele in 'einhil.dem' und
'bradic.dem'.


File: maxima.info,  Node: Paket itensor,  Next: Paket ctensor,  Prev: Tensorpakete in Maxima,  Up: Tensoren

20.2 Paket ITENSOR
==================

* Menu:

* Einführung in itensor::
* Funktionen und Variablen für itensor::


File: maxima.info,  Node: Einführung in itensor,  Next: Funktionen und Variablen für itensor,  Prev: Paket itensor,  Up: Paket itensor

20.2.1 Einführung in ITENSOR
----------------------------

Das Paket 'itensor' für das Rechnen mit Tensoren in der Indexnotation
wird mit dem Kommando 'load(itensor)' geladen.  Mit dem Kommando
'demo(tensor)' wird eine Liste mit verschiedenen Beispielen angezeigt.

Im Paket 'itensor' werden Tensoren als indiziertes Objekte dargestellt.
Ein indiziertes Objekt ist eine Funktion mit drei Gruppen an Indizes,
die die kovarianten, kontravarianten und Ableitungsindizes eines Tensors
darstellen.  Das erste Argument der Funktion ist eine Liste der
kovarianten Indizes und das zweite Argument die Liste der
kontravarianten Indizes.  Hat der Tensor keine entsprechenden
Komponenten, dann wird eine leere Liste als Argument angegeben.  Zum
Beispiel repräsentiert 'g([a,b], [c]' einen Tensor 'g', der zwei
kovariante Indizes '[a,b]', einen kontravarianten Index '[c]' und keinen
Ableitungsindex hat.  Mit der Funktion 'ishow' werden Tensoren in einer
besonderen Schreibweise ausgegeben.

Beispiele:

     (%i1) load(itensor)$

     (%i2) g([a,b], [c]);
     (%o2)                    g([a, b], [c])

     (%i3) ishow(g([a,b], [c]))$
                                    c
     (%t3)                         g
                                    a b

Ableitungsindizes werden als weitere Argumente der Funktion hinzugefügt,
die den Tensor repräsentiert.  Ableitungsindizes können vom Nutzer
angegeben oder bei der Ableitung von Tensoren von Maxima hinzugefügt
werden.  Im Allgemeinen ist die Differentiation kommutativ, so dass die
Reihenfolge der Ableitungsindizes keine Rolle spielt.  Daher werden die
Indizes von Maxima bei der Vereinfachung mit Funktionen wie 'rename'
alphabetisch sortiert.  Dies ist jedoch nicht der Fall, wenn bewegte
Bezugssysteme genutzt werden, was mit der Optionsvariablen 'iframe_flag'
angezeigt wird, die in diesem Fall den Wert 'true' erhält.  Es ist zu
beachten, dass mit dem Paket 'itensor' Ableitungsindizes nicht angehoben
werden können und nur als kovariante Indizes auftreten.

Beispiele:

     (%i1) load(itensor)$

     (%i2) ishow(t([a,b],[c],j,i))$
                                  c
     (%t2)                       t
                                  a b,j i
     (%i3) ishow(rename(%))$
                                  c
     (%t3)                       t
                                  a b,i j
     (%i4) ishow(t([a,b],[c],j,i) - t([a,b],[c],i,j))$
                             c          c
     (%t4)                  t        - t
                             a b,j i    a b,i j
     (%i5) ishow(rename(%))$
     (%t5)                           0
     (%i6) iframe_flag:true;
     (%o6)                         true
     (%i7) ishow(t([a,b],[c],j,i) - t([a,b],[c],i,j))$
                             c          c
     (%t7)                  t        - t
                             a b,j i    a b,i j
     (%i8) ishow(rename(%))$
                             c          c
     (%t8)                  t        - t
                             a b,j i    a b,i j

Das folgende Beispiel zeigt einen Ausdruck mit verschiedenen Ableitungen
eines Tensors 'g'.  Ist 'g' der metrische Tensor, dann entspricht das
Ergebnis der Definition des Christoffel-Symbols der ersten Art.

     (%i1) load(itensor)$

     (%i2) ishow(1/2*(idiff(g([i,k],[]),j) + idiff(g([j,k],[]),i)
                                           - idiff(g([i,j],[]),k)))$
                         g      + g      - g
                          j k,i    i k,j    i j,k
     (%t2)               ------------------------
                                    2

Tensoren werden standardmäßig nicht als symmetrisch angenommen.  Erhält
die Optionsvariable 'allsym' den Wert 'true', dann werden alle Tensoren
als symmetrisch in den kovarianten und kontravarianten Indizes
angenommen.

Das Paket 'itensor' behandelt Tensoren im Allgemeinen als opake Objekte.
Auf Tensorgleichungen werden algebraischen Regeln insbesondere
Symmetrieregeln und Regeln für die Tensorverjüngung angewendet.
Weiterhin kennt 'itensor' die kovariante Ableitung, Krümmung und die
Torsion.  Rechnungen können in bewegten Bezugssystemen ausgeführt
werden.

Beispiele:

Die folgenden Beispiele zeigen einige Anwendungen des Paketes 'itensor'.

     (%i1) load(itensor);
     (%o1)      /share/tensor/itensor.lisp
     (%i2) imetric(g);
     (%o2)                                done
     (%i3) components(g([i,j],[]),p([i,j],[])*e([],[]))$
     (%i4) ishow(g([k,l],[]))$
     (%t4)                               e p
                                            k l
     (%i5) ishow(diff(v([i],[]),t))$
     (%t5)                                  0
     (%i6) depends(v,t);
     (%o6)                               [v(t)]
     (%i7) ishow(diff(v([i],[]),t))$
                                         d
     (%t7)                               -- (v )
                                         dt   i
     (%i8) ishow(idiff(v([i],[]),j))$
     (%t8)                                v
                                           i,j
     (%i9) ishow(extdiff(v([i],[]),j))$
     (%t9)                             v    - v
                                        j,i    i,j
                                       -----------
                                            2
     (%i10) ishow(liediff(v,w([i],[])))$
                                    %3          %3
     (%t10)                        v   w     + v   w
                                        i,%3    ,i  %3
     (%i11) ishow(covdiff(v([i],[]),j))$
                                                   %4
     (%t11)                        v    - v   ichr2
                                    i,j    %4      i j
     (%i12) ishow(ev(%,ichr2))$
                     %4 %5
     (%t12) v    - (g      v   (e p       + e   p     - e p       - e    p
             i,j            %4     j %5,i    ,i  j %5      i j,%5    ,%5  i j

                                              + e p       + e   p    ))/2
                                                   i %5,j    ,j  i %5
     (%i13) iframe_flag:true;
     (%o13)                               true
     (%i14) ishow(covdiff(v([i],[]),j))$
                                                  %6
     (%t14)                        v    - v   icc2
                                    i,j    %6     i j
     (%i15) ishow(ev(%,icc2))$
                                                  %6
     (%t15)                        v    - v   ifc2
                                    i,j    %6     i j
     (%i16) ishow(radcan(ev(%,ifc2,ifc1)))$
                  %6 %7                    %6 %7
     (%t16) - (ifg      v   ifb       + ifg      v   ifb       - 2 v
                         %6    j %7 i             %6    i j %7      i,j

                                                  %6 %7
                                             - ifg      v   ifb      )/2
                                                         %6    %7 i j
     (%i17) ishow(canform(s([i,j],[])-s([j,i])))$
     (%t17)                            s    - s
                                        i j    j i
     (%i18) decsym(s,2,0,[sym(all)],[]);
     (%o18)                               done
     (%i19) ishow(canform(s([i,j],[])-s([j,i])))$
     (%t19)                                 0
     (%i20) ishow(canform(a([i,j],[])+a([j,i])))$
     (%t20)                            a    + a
                                        j i    i j
     (%i21) decsym(a,2,0,[anti(all)],[]);
     (%o21)                               done
     (%i22) ishow(canform(a([i,j],[])+a([j,i])))$
     (%t22)                                 0


File: maxima.info,  Node: Funktionen und Variablen für itensor,  Prev: Einführung in itensor,  Up: Paket itensor

20.2.2 Funktionen und Variablen für ITENSOR
-------------------------------------------

* Menu:

* Behandlung indizierter Größen::
* Tensorsymmetrien::
* Tensoranalysis::
* Tensoren in gekrümmten Räumen::
* Begleitende Vielbeine::
* Torsion und Nichtmetrizität::
* Graßmann-Algebra::
* Exportiere als TeX::
* Schnittstelle zum Paket ctensor::
* Reservierte Bezeichner::


File: maxima.info,  Node: Behandlung indizierter Größen,  Next: Tensorsymmetrien,  Prev: Funktionen und Variablen für itensor,  Up: Funktionen und Variablen für itensor

20.2.2.1 Behandlung indizierter Größen
......................................

 -- Funktion: canten (<expr>)

     Ist vergleichbar mit der Funktion 'rename' und vereinfacht den
     Ausdruck <expr> indem gebundene Indizes umbenannt und permutiert
     werden.  Wie die Funktion 'rename' kann 'canten' nur Ausdrücke mit
     Summen von Tensorprodukten vereinfachen, in denen keine Ableitungen
     nach Tensorkomponenten auftreten.  Daher sollte 'canten' nur
     verwendet werden, wenn sich mit der Funktion 'canform' nicht die
     gewünschte Vereinfachung eines Ausdrucks erzielen lässt.

     Das Ergebnis der Funktion 'canten' ist mathematisch nur korrekt,
     wenn die Tensoren symmetrisch in ihren Indizes sind.  Hat die
     Optionsvariable 'allsym' _nicht_ den Wert 'true', bricht 'canten'
     mit einer Fehlermeldung ab.

     Siehe auch die Funktion 'concan', mit der Ausdrücke mit Tensoren
     ebenfalls vereinfacht werden können, wobei 'concan' zusätzlich
     Tensorverjüngungen ausführt.

 -- Funktion: changename (<old>, <new>, <expr>)

     Ändert den Namen aller Tensoren im Ausdruck <expr> von <old> nach
     <new>.  Das Argument <old> kann ein Symbol oder eine Liste der Form
     '[<name>, <m>, <n>]' sein.  Im letzteren Fall werden nur die
     Tensoren zu <new> umbenannt, die den Namen <name> sowie <m>
     kovariante und <n> kontravariante Indizes haben.

     Beispiel:

     In diesem Beispiel wird der Name <c> zu <w> geändert.

          (%i1) load(itensor)$

          (%i2) expr:a([i,j],[k])*b([u],[],v)+c([x,y],[])*d([],[])*e$

          (%i3) ishow(changename(c, w, expr))$
                                            k
          (%t3)                 d e w    + a    b
                                     x y    i j  u,v

 -- Funktion: components (<tensor>, <expr>)

     Erlaubt die Zuweisung von Werten an die Komponenten eines Tensors
     <tensor>, die mit dem Argument <expr> angegeben werden.  Immer wenn
     der Tensor <tensor> mit all seinen Indizes in einem Ausdruck
     auftritt, werden die Komponenten mit den angegebenen Werten
     substituiert.  Der Tensor muss die Form 't([...],[...])' haben,
     wobei die Listen auch leer sein können.  Das Argument <expr> ist
     irgendein Ausdruck, der dieselben freien Indizes wie der Tensor
     <tensor> hat.  Sollen Werte an einen Metriktensor zugewiesen
     werden, der Dummy-Indizes hat, so muss auf die Benennung der
     Indizes sorgfältig geachtet werden, um das Auftreten von Mehrfachen
     Dummy-Indizes zu vermeiden.  Mit der Funktion 'remcomps' werden
     Zuweisungen der Funktion 'components' an die Komponenten eines
     Tensors entfernt.

     Es muss beachtet werden, dass die Funktion 'components' nur den Typ
     eines Tensors, aber nicht die Ordnung der Indizes beachtet.  Werden
     daher Werte an die Komponenten der Tensoren 'x([i,-j],[])',
     'x([-j,i],[])' oder 'x([i],[j])' zugewiesen, ergibt sich jeweils
     dasselbe Ergebnis.

     Komponenten können einem indizierten Ausdruck auf vier verschiedene
     Methoden zugeordnet werden.  Zwei Methoden nutzen die Funktion
     'components'.

     1) Als ein indizierte Ausdruck:

          (%i2) components(g([],[i,j]), e([],[i])*p([],[j]))$
          (%i3) ishow(g([],[i,j]))$
                                                i  j
          (%t3)                                e  p

     2) Als eine Matrix:

          (%i5) lg:-ident(4)$ lg[1,1]:1$ lg;
                                      [ 1   0    0    0  ]
                                      [                  ]
                                      [ 0  - 1   0    0  ]
          (%o5)                       [                  ]
                                      [ 0   0   - 1   0  ]
                                      [                  ]
                                      [ 0   0    0   - 1 ]

          (%i6) components(g([i,j],[]), lg);
          (%o6)                                done
          (%i7) ishow(g([i,j],[]))$
          (%t7)                                g
                                                i j
          (%i8) g([1,1],[]);
          (%o8)                                  1
          (%i9) g([4,4],[]);
          (%o9)                                 - 1

     3) Als eine Funktion: Die Werte der Komponenten eines Tensors
     werden durch eine Funktion gegeben.

          (%i4) h(l1,l2,[l3]):=if length(l1)=length(l2) and length(l3)=0
            then kdelta(l1,l2) else apply(g,append([l1,l2], l3))$
          (%i5) ishow(h([i],[j]))$
                                                    j
          (%t5)                               kdelta
                                                    i
          (%i6) ishow(h([i,j],[k],l))$
                                               k
          (%t6)                               g
                                               i j,l

     4) Mit Mustern und Regeln: Im Folgenden wird ein Beispiel mit den
     Funktionen 'defrule' und 'applyb1' gezeigt.

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) matchdeclare(l1,listp);
          (%o2)                                done
          (%i3) defrule(r1,m(l1,[]),(i1:idummy(),
                g([l1[1],l1[2]],[])*q([i1],[])*e([],[i1])))$

          (%i4) defrule(r2,m([],l1),(i1:idummy(),
                w([],[l1[1],l1[2]])*e([i1],[])*q([],[i1])))$

          (%i5) ishow(m([i,n],[])*m([],[i,m]))$
                                              i m
          (%t5)                              m    m
                                                   i n
          (%i6) ishow(rename(applyb1(%,r1,r2)))$
                                     %1  %2  %3 m
          (%t6)                     e   q   w     q   e   g
                                                   %1  %2  %3 n

 -- Funktion: concan (<expr>)

     Ist vergleichbar mit der Funktion 'canten'.  Im Unterschied zu
     'canten' werden zusätzlich Tensorverjüngungen ausgeführt.

 -- Funktion: contract (<expr>)

     Führt die Tensorverjüngungen im Ausdruck <expr> aus, die beliebige
     Summen und Produkte sein können.  'contract' nutzt die
     Informationen, die für die Tensoren mit der Funktion 'defcon'
     definiert sind.  Die besten Ergebnisse werden erzielt, wenn der
     Ausdruck <expr> vollständig expandiert wird.  Die Funktion
     'radexpand' expandiert Produkte und Potenzen von Summen am
     schnellsten, sofern keine Variablen im Nenner der Terme auftreten.
     Die Optionsvariable 'gcd' sollte den Wert 'false' haben, wenn das
     Kürzen durch einen größten gemeinsamen Teiler nicht notwendig ist.

 -- Systemvariable: contractions

     Die Liste 'contractions' enthält die Tensoren, die mit der Funktion
     'defcon' die Eigenschaft einer Tensorverjüngung erhalten haben.

 -- Funktion: defcon (<tensor_1>)
 -- Funktion: defcon (<tensor_1>, <tensor_2>, <tensor_3>)

     Gibt einem Tensor <tensor_1> die Eigenschaft, dass die
     Tensorverjüngung des Produktes <tensor_1> mit <tensor_2> das
     Ergebnis <tensor_3> hat.  Wird nur ein Argument <tensor_1>
     angegeben, dann hat die Tensorverjüngung für jeden Tensor 'tensor',
     der die korrekten Indizes hat, das Ergebnis 'tensor' mit neuen
     Indizes, die die Tensorverjüngung widerspiegeln.

     Wird zum Beispiel die Metrik als 'imetric: g' gesetzt, dann wird
     mit 'defcon(g)' das Hochstellen und Herunterstellen der Indizes mit
     dem Metriktensor definiert.

     Wird 'defcon' wiederholt für einen Tensor aufgerufen, ist jeweils
     die letzte Definition wirksam.

     Die Liste 'contractions' enthält die Tensoren, die mit der Funktion
     'defcon' die Eigenschaft einer Tensorverjüngung erhalten haben.

 -- Funktion: dispcon (<tensor_1>, <tensor_2>, ...)
 -- Funktion: dispcon (all)

     Zeigt die Kontraktionseigenschaften der Tensoren <tensor_1>,
     <tensor_2>, ... wie sie mit der Funktion 'defcon' definiert wurden.
     Das Kommando 'dispcon(all)' zeigt alle vom Nutzer definierten
     Kontraktionseigenschaften.

     Beispiel:

     Wird das Paket 'itensor' geladen, gibt 'dispcon' das folgende
     Ergebnis.

          (%i1) load(itensor)$

          (%i2) dispcon(all);
          (%o2)      [[[ifr, ifri, ifg]], [[ifg, ifg, kdelta]]]

 -- Funktion: entertensor (<name>)

     Die Funktion 'entertensor' ermöglicht die Eingabe eines indizierten
     Tensors mit einer beliebigen Anzahl an Tensorindizes und
     Ableitungen.  Es kann ein einzelner Index oder eine Liste mit
     Indizes angegeben werden.  Die Liste kann eine leere Liste sein.

     Beispiel:

          (%i1) load(itensor)$

          (%i2) entertensor()$
          Enter tensor name: a;
          Enter a list of the covariant indices: [i,j];
          Enter a list of the contravariant indices: [k];
          Enter a list of the derivative indices: [];
                                         k
          (%t2)                         a
                                         i j

 -- Optionsvariable: flipflag
     Standardwert: 'false'

     Hat die Optionsvariable 'flipflag' den Wert 'false', werden die
     Indizes von der Funktion 'rename' bei der Umbenennung in der
     Reihenfolge der kontravarianten Indizes sortiert, ansonsten in der
     Reihenfolge der kovarianten Indizes.

     Siehe auch das Beispiel für die Funktion 'rename'.

 -- Optionsvariable: icounter
     Standardwert: '0'

     Enthält die laufende Nummer, um den nächsten Dummy-Index zu bilden.
     'icounter' wird automatisch erhöht, bevor der neue Index gebildet
     wird.  Dem Wert 'icounter' wird er Präfix 'idummyx' vorangestellt.
     Der Standardwert von 'idummyx' ist '%'.

 -- Funktion: idummy ()

     Erhöht den Wert der laufenden Nummer 'icounter' und gibt einen
     neuen Index zurück, indem der Präfix 'idummyx' der Nummer
     'icounter' vorangestellt wird.  Siehe auch die Funktion 'indices'.

 -- Optionsvariable: idummyx
     Standardwert: '%'

     Enthält den Präfix, der einem neuen Index vorangestellt wird, der
     mit der Funktion 'idummy' gebildet wird.

 -- Funktion: indexed_tensor (<tensor>)

     Muss ausgeführt werden, bevor einem Tensors <tensor> Komponenten
     zugewiesen werden, für die bereits interne Werte vorliegen wie für
     'ichr1', 'ichr2' oder 'icurvature'.  Siehe das Beispiel zur
     Funktion 'icurvature'.

 -- Funktion: indices (<expr>)

     Gibt eine Liste mit zwei Elementen zurück.  Das erste Element ist
     eine Liste mit den Indizes im Ausdruck <expr> die frei sind, also
     nur einmal auftreten.  Das zweite Elemente ist eine Liste mit den
     Indizes, über die summiert wird, die also im Ausdruck genau zweimal
     auftreten.

     Ein Tensorprodukt mit einem Index der mehr als zweimal auftritt,
     ist nicht korrekt formuliert.  Die Funktion 'indices' gibt in einem
     solchen Fall jedoch keinen Fehler aus.

     Beispiel:

          (%i1) load(itensor)$

          (%i2) ishow(a([i,j],[k,l],m,n)*b([k,o],[j,m,p],q,r))$
                                   k l      j m p
          (%t2)                   a        b
                                   i j,m n  k o,q r
          (%i3) indices(%);
          (%o3)          [[l, p, i, n, o, q, r], [k, j, m]]

 -- Funktion: ishow (<expr>)

     Zeigt den Ausdruck <expr> an, wobei Tensoren im Ausdruck mit
     tiefgestellten kovarianten Indizes und hochgestellten
     kontravarianten Indizes sowie die Ableitungen mit durch ein Komma
     getrennten tiefgestellte Indizes angezeigt werden.

     Beispiel:

          (%i1) load(itensor)$

          (%i2) ishow(a([i,j], [k], v,w))$
                                       k
          (%t2)                       a
                                       i j,v w

 -- Funktion: kdels (<L1>, <L2>)

     'kdels' gibt wie die Funktion 'kdelta' ein Kronecker-Delta zurück.
     Im Unterschied zu 'kdelta' ist das Kronecker-Delta der Funktion
     'kdels' symmetrisch.

     Beispiele:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) kdelta([1,2],[2,1]);
          (%o2)                                 - 1
          (%i3) kdels([1,2],[2,1]);
          (%o3)                                  1
          (%i4) ishow(kdelta([a,b],[c,d]))$
                                       c       d         d       c
          (%t4)                  kdelta  kdelta  - kdelta  kdelta
                                       a       b         a       b
          (%i4) ishow(kdels([a,b],[c,d]))$
                                       c       d         d       c
          (%t4)                  kdelta  kdelta  + kdelta  kdelta
                                       a       b         a       b

 -- Funktion: kdelta (<L1>, <L2>)

     Ist das verallgemeinerte Kronecker-Delta im 'itensor'-Paket.  Das
     Argument <L1> ist die Liste der kovarianten und <L2> der
     kontravarianten Indizes.  'kdelta([i],[j])' gibt das einfache
     Kronecker-Delta zurück.

     Das 'itensor'-Paket erlaubt die Definition des Kronecker-Delta nur
     mit kovarianten oder kontravarianten Indizes, wie zum Beispiel
     'kdelta([i,j],[])'.  Mit diesen Größen kann gerechnet werden, sie
     sind jedoch keine Tensoren.

 -- Regel: lc_l

     'lc_l' ist eine Regel, um Ausdrücke zu vereinfachen, die
     Levi-Civita-Symbole enthalten.  Zusammen mit der Regel 'lc_u' kann
     die Regel zum Beispiel mit der Funktion 'applyb1' angewendet
     werden, um Ausdrücke effizienter zu vereinfachen, als durch eine
     Auswertung des Symbols 'levi_civita'.

     Beispiele:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) el1:ishow('levi_civita([i,j,k],[])*a([],[i])*a([],[j]))$
                                       i  j
          (%t2)                       a  a  levi_civita
                                                       i j k
          (%i3) el2:ishow('levi_civita([],[i,j,k])*a([i])*a([j]))$
                                                 i j k
          (%t3)                       levi_civita      a  a
                                                        i  j
          (%i4) canform(contract(expand(applyb1(el1,lc_l,lc_u))));
          (%t4)                                  0
          (%i5) canform(contract(expand(applyb1(el2,lc_l,lc_u))));
          (%t5)                                  0

 -- Regel: lc_u

     'lc_u' ist eine Regel, um Ausdrücke zu vereinfachen, die
     Levi-Civita-Symbole enthalten.  Zusammen mit der Regel 'lc_c' kann
     die Regel zum Beispiel mit der Funktion 'applyb1' angewendet
     werden, um Ausdrücke effizienter zu vereinfachen, als durch eine
     Auswertung des Symbols 'levi_civita'.  Siehe 'lc_l' für Beispiele.

 -- Funktion: lc2kdt (<expr>)

     Vereinfacht den Ausdruck <expr> mit Levi-Civita-Symbolen.  Wenn
     möglich werden diese zu Kronecker-Delta-Symbolen vereinfacht.  Im
     Unterschied zu der Auswertung eines Ausdrucks mit
     Levi-Civita-Symbolen, vermeidet die Funktion 'lc2kdt' das Einführen
     von numerischen Indizes, die für eine weitere symbolische
     Vereinfachung zum Beispiel mit den Funktionen 'rename' oder
     'contract' nicht geeignet sind.

     Beispiel:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) expr:ishow('levi_civita([],[i,j])
                           *'levi_civita([k,l],[])*a([j],[k]))$
                                            i j  k
          (%t2)                  levi_civita    a  levi_civita
                                                 j            k l
          (%i3) ishow(ev(expr,levi_civita))$
                                            i j  k       1 2
          (%t3)                       kdelta    a  kdelta
                                            1 2  j       k l
          (%i4) ishow(ev(%,kdelta))$
                       i       j         j       i   k
          (%t4) (kdelta  kdelta  - kdelta  kdelta ) a
                       1       2         1       2   j

                                         1       2         2       1
                                  (kdelta  kdelta  - kdelta  kdelta )
                                         k       l         k       l
          (%i5) ishow(lc2kdt(expr))$
                               k       i       j    k       j       i
          (%t5)               a  kdelta  kdelta  - a  kdelta  kdelta
                               j       k       l    j       k       l
          (%i6) ishow(contract(expand(%)))$
                                           i           i
          (%t6)                           a  - a kdelta
                                           l           l

     Die Funktion 'lc2kdt' benötigt in einigen Fällen den Metriktensor.
     Ist der Metriktensor zuvor nicht mit der Funktion 'imetric'
     definiert, dann meldet Maxima einen Fehler.

          (%i7) expr:ishow('levi_civita([],[i,j])
                           *'levi_civita([],[k,l])*a([j,k],[]))$
                                           i j            k l
          (%t7)                 levi_civita    levi_civita    a
                                                               j k
          (%i8) ishow(lc2kdt(expr))$
          Maxima encountered a Lisp error:

           Error in $IMETRIC [or a callee]:
           $IMETRIC [or a callee] requires less than two arguments.

          Automatically continuing.
          To reenable the Lisp debugger set *debugger-hook* to nil.
          (%i9) imetric(g);
          (%o9)                                done
          (%i10) ishow(lc2kdt(expr))$
                   %3 i       k   %4 j       l     %3 i       l   %4 j
          (%t10) (g     kdelta   g     kdelta   - g     kdelta   g
                              %3             %4               %3
                        k
                  kdelta  ) a
                        %4   j k
          (%i11) ishow(contract(expand(%)))$
                                            l i    l i  j
          (%t11)                           a    - g    a
                                                        j

 -- Funktion: levi_civita (<L>)

     Ist der Levi-Civita-Tensor, der auch Permutationstensor genannt
     wird.  Der Tensor hat den Wert '1', wenn die Liste <L> eine gerade
     Permutation ganzer Zahlen ist, den Wert '-1' für eine ungerade
     Permutation und ansonsten den Wert '0'.

     Beispiel:

     Für eine Kreisbewegung ist die Bahngeschwindigkeit 'v' das
     Kreuzprodukt aus Winkelgeschwindigkeit 'w' und Ortsvektor 'r'.  Wir
     haben also 'v = w x r'.  Hier wird eine tensorielle Schreibweise
     des Kreuzproduktes mit dem Levi-Civita-Tensor eingeführt.  Der
     Ausdruck wird sodann für die erste Komponente zu der bekannten
     Definition des Kreuzproduktes vereinfacht.

          (%i1) load(itensor)$

          (%i2) ishow(v([],[a])=
                     'levi_civita([],[a,b,c])*w([b],[])*r([c],[]))$
                              a              a b c
          (%t2)              v  = levi_civita      w  r
                                                    b  c
          (%i3) ishow(subst([a=1],%))$
                              1              1 b c
          (%t3)              v  = levi_civita      w  r
                                                    b  c
          (%i4) ishow(ev(%, levi_civita))$
                                1         1 b c
          (%t4)                v  = kdelta      w  r
                                          1 2 3  b  c
          (%i5) ishow(expand(ev(%, kdelta)))$
                  1         b       c               c       b
          (%t5)  v  = kdelta  kdelta  w  r  - kdelta  kdelta  w  r
                            2       3  b  c         2       3  b  c
          (%i6) ishow(contract(%))$
                                  1
          (%t6)                  v  = w  r  - r  w
                                       2  3    2  3

     In diesem Beispiel wird das Spatprodukt von drei Vektoren 'a', 'b'
     und 'b' mit dem Levi-Civita-Tensor definiert und dann vereinfacht.

          (%i1) load(itensor)$

          (%i2) ishow(levi_civita([],[i,j,k])*a([i],[])*b([j],[])*c([k],[]))$
                                      i j k
          (%t2)                 kdelta      a  b  c
                                      1 2 3  i  j  k
          (%i3) ishow(contract(expand(ev(%,kdelta))))$
          (%t3) a  b  c  - b  a  c  - a  c  b  + c  a  b  + b  c  a
                 1  2  3    1  2  3    1  2  3    1  2  3    1  2  3
                                                                 - c  b  a
                                                                    1  2  3

 -- Funktion: listoftens (<expr>)

     Gibt eine Liste mit allen Tensoren zurück, die im Argument <expr>
     enthalten sind.

     Beispiel:

          (%i1) load(itensor)$

          (%i2) ishow(a([i,j],[k])*b([u],[],v)+c([x,y],[])*d([],[])*e)$
                                            k
          (%t2)                 d e c    + a    b
                                     x y    i j  u,v
          (%i3) ishow(listoftens(%))$
                                  k
          (%t3)                 [a   , b   , c   , d]
                                  i j   u,v   x y

 -- Funktion: remcomps (<tensor>)

     Entfernt alle Werte von den Komponenten des Tensors <tensor>, die
     einen Wert mit der Funktion 'components' erhalten haben.

 -- Funktion: remcon (<tensor_1>, ..., <tensor_n>)
 -- Funktion: remcon (all)

     Entfernt die Eigenschaften der Tensorverjüngung von den Tensoren
     <tensor_1>, ..., <tensor_n>.  'remcon(all)' entfernt die
     Eigenschaften von der Tensorverjüngung für alle Tensoren.  Das sind
     die Tensoren, die in der Liste 'contractions' enthalten sind.

 -- Funktion: rename (<expr>)
 -- Funktion: rename (<expr>, <count>)

     Gibt einen zum Argument <expr> äquivalenten Ausdruck zurück, wobei
     die Summationsindizes mit den Werten aus der liste '[%1, %2, ...]'
     umbenannt sind.  Wird das zusätzlich das Argument <count>
     angegeben, wird die Nummerierung mit dem Wert <count> begonnen.
     Jeder Summationsindex in einem Produkt erhält einen verschiedenen
     Namen.  Für eine Summe wird der Zähler für jeden Term
     zurückgesetzt.  Auf diese Weise wirkt die Funktion 'rename' wie
     eine Vereinfachung eines tensoriellen Ausdrucks.  Hat die
     Optionsvariable 'allsym' den Wert 'true', werden die Indizes
     alphabetisch nach den kovarianten oder kontravarianten Indizes
     geordnet, entsprechend dem Wert der Optionsvariablen 'flipflag'.
     Hat die Optionsvariable 'flipflag' den Wert 'true', werden die
     Indizes entsprechend der Ordnung der kovarianten Indizes geordnet.
     Es ist häufig der Fall, dass das Ordnen sowohl nach den kovarianten
     als auch den kontravarianten Indizes einen Ausdruck besser
     vereinfacht, als allein die Ordnung nach einer der Indizes.

     Beispiele:

          (%i1) load(itensor)$

          (%i2) allsym: true;
          (%o2)                         true
          (%i3) g([],[%4,%5])*g([],[%6,%7])*ichr2([%1,%4],[%3])
                       *ichr2([%2,%3],[u])*ichr2([%5,%6],[%1])
                       *ichr2([%7,r],[%2])
           -g([],[%4,%5])*g([],[%6,%7])*ichr2([%1,%2],[u])
                         *ichr2([%3,%5],[%1])*ichr2([%4,%6],[%3])
                         *ichr2([%7,r],[%2])$

          (%i4) expr: ishow(%)$
                 %4 %5  %6 %7      %3         u          %1         %2
          (%t4) g      g      ichr2      ichr2      ichr2      ichr2
                                   %1 %4      %2 %3      %5 %6      %7 r
                    %4 %5  %6 %7      u          %1         %3         %2
                 - g      g      ichr2      ichr2      ichr2      ichr2
                                      %1 %2      %3 %5      %4 %6      %7 r
          (%i5) flipflag: true;
          (%o5)                         true
          (%i6) ishow(rename(expr))$
                 %2 %5  %6 %7      %4         u          %1         %3
          (%t6) g      g      ichr2      ichr2      ichr2      ichr2
                                   %1 %2      %3 %4      %5 %6      %7 r
                    %4 %5  %6 %7      u          %1         %3         %2
                 - g      g      ichr2      ichr2      ichr2      ichr2
                                      %1 %2      %3 %4      %5 %6      %7 r
          (%i7) flipflag: false;
          (%o7)                         false
          (%i8) rename(%th(2));
          (%o8)                           0
          (%i9) ishow(rename(expr))$
                 %1 %2  %3 %4      %5         %6         %7        u
          (%t9) g      g      ichr2      ichr2      ichr2     ichr2
                                   %1 %6      %2 %3      %4 r      %5 %7
                    %1 %2  %3 %4      %6         %5         %7        u
                 - g      g      ichr2      ichr2      ichr2     ichr2
                                      %1 %3      %2 %6      %4 r      %5 %7

 -- Funktion: showcomps (<tensor>)

     Zeigt die Zuweisungen mit der Funktion 'components' an die
     Komponenten des Tensors <tensor>.  Die Funktion 'showcomps' kann
     auch die Komponenten eines Tensors mit einer höheren Stufe als 2
     zeigen.

     Beispiel:

          (%i1) load(ctensor)$
          (%i2) load(itensor)$
          (%i3) lg:matrix([sqrt(r/(r-2*m)),0,0,0],[0,r,0,0],
                          [0,0,sin(theta)*r,0],[0,0,0,sqrt((r-2*m)/r)]);
                         [         r                                     ]
                         [ sqrt(-------)  0       0              0       ]
                         [      r - 2 m                                  ]
                         [                                               ]
                         [       0        r       0              0       ]
          (%o3)          [                                               ]
                         [       0        0  r sin(theta)        0       ]
                         [                                               ]
                         [                                      r - 2 m  ]
                         [       0        0       0        sqrt(-------) ]
                         [                                         r     ]
          (%i4) components(g([i,j],[]),lg);
          (%o4)                                done
          (%i5) showcomps(g([i,j],[]));
                            [         r                                     ]
                            [ sqrt(-------)  0       0              0       ]
                            [      r - 2 m                                  ]
                            [                                               ]
                            [       0        r       0              0       ]
          (%t5)      g    = [                                               ]
                      i j   [       0        0  r sin(theta)        0       ]
                            [                                               ]
                            [                                      r - 2 m  ]
                            [       0        0       0        sqrt(-------) ]
                            [                                         r     ]
          (%o5)                                false


File: maxima.info,  Node: Tensorsymmetrien,  Next: Tensoranalysis,  Prev: Behandlung indizierter Größen,  Up: Funktionen und Variablen für itensor

20.2.2.2 Tensorsymmetrien
.........................

 -- Optionsvariable: allsym
     Standardwert: 'false'

     Hat die Optionsvariable 'allsym' den Wert 'true', werden alle
     indizierten Größen als symmetrisch in ihren kovarianten und
     kontravarianten Indizes angenommen.  Ist der Wert 'false', werden
     keine Symmetrien für die Indizes angenommen.  Die Indizes von
     Ableitungen werden immer als symmetrisch angenommen, außer wenn die
     Optionsvariable 'iframe_flag' den Wert 'true' hat.

 -- Funktion: decsym (<tensor>, <m>, <n>, [<cov_1>, <cov_2>, ...],
          [<contr_1>, <contr_2>, ...])

     Definiert Symmetrieeigenschaften für den Tensor <tensor> mit <m>
     kovarianten und <n> kontravarianten Indizes.  Die Argumente <cov_i>
     und <contr_i> geben Symmetrieeigenschaften zwischen den
     kontravarianten und kontravarianten Indizes an.  Die Argumente
     haben die Form 'symoper(<index_1>, <index_2, ...>'.  'symoper' ist
     einer der Symmetrieeigenschaften 'sym' für symmetrisch, 'anti' für
     antisymmetrisch oder 'cyc' für zyklisch und die Argumente <index_i>
     sind ganze Zahlen, die die Position des Index im Tensor <tensor>
     angegeben.  Weiterhin ist die Form 'symoper(all)' möglich.  In
     diesem Fall wird die entsprechende Symmetrieeigenschaft für alle
     Indizes angenommen.

     Ist zum Beispiel 'b' ein Tensor mit 5 kovarianten Indizes, dann
     wird mit 'decsym(b, 5, 3, [sym(1,2), anti(3,4)], [cyc(all)])'
     definiert, dass 'b' symmetrisch in den Indizes '1' und '2',
     antisymmetrisch in den Indizes '3' und '4' sowie zyklisch in allen
     kontravarianten Indizes ist.

     Symmetrieeigenschaften, die mit der Funktion 'decsym' definiert
     werden, werden von der Funktion 'canform' angewendet.

     Beispiele:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) expr:contract( expand( a([i1, j1, k1], [])
                     *kdels([i, j, k], [i1, j1, k1])))$
          (%i3) ishow(expr)$
          (%t3)         a      + a      + a      + a      + a      + a
                         k j i    k i j    j k i    j i k    i k j    i j k
          (%i4) decsym(a,3,0,[sym(all)],[]);
          (%o4)                                done
          (%i5) ishow(canform(expr))$
          (%t5)                              6 a
                                                i j k
          (%i6) remsym(a,3,0);
          (%o6)                                done
          (%i7) decsym(a,3,0,[anti(all)],[]);
          (%o7)                                done
          (%i8) ishow(canform(expr))$
          (%t8)                                  0
          (%i9) remsym(a,3,0);
          (%o9)                                done
          (%i10) decsym(a,3,0,[cyc(all)],[]);
          (%o10)                               done
          (%i11) ishow(canform(expr))$
          (%t11)                        3 a      + 3 a
                                           i k j      i j k
          (%i12) dispsym(a,3,0);
          (%o12)                     [[cyc, [[1, 2, 3]], []]]

 -- Funktion: remsym (<tensor>, <m>, <n>)

     Entfernt die Symmetrieeigenschaften des Tensors <tensor>, der <m>
     kovariante und <n> kontravariante Indizes hat.

 -- Funktion: canform (<expr>)
 -- Funktion: canform (<expr>, <rename>)

     Vereinfacht den Ausdruck <expr> indem alle Dummy-Indizes umbenannt
     und umgeordnet werden, wobei vorhandene Symmetrieeigenschaften
     angewendet werden.  Hat die Optionsvariable 'allsym' den Wert
     'true', werden alle Indizes als symmetrisch angenommen.  Ansonsten
     werden Symmetrieeigenschaften angewendet, die mit der Funktion
     'decsym' definiert sind.  Die Dummy-Indizes werden auf gleiche
     Weise umbenannt wie von der Funktion 'rename'.  Wird 'canform' auf
     einen großen Ausdruck angewendet, kann die Ausführung eine lange
     Zeit beanspruchen.  Die Rechenzeit kann verkürzt werden, indem
     zuerst die Funktion 'rename' auf den Ausdruck angewendet wird.

     'canform' kann einen Ausdruck nicht immer in die einfachste Form
     bringen, jedoch ist das Ergebnis immer mathematisch korrekt.

     Erhält das optionale zweite Argument <rename> den Wert 'false',
     wird die Umbenennung mit der Funktion 'rename' nicht ausgeführt.

     Für ein Beispiel siehe die Funktion 'decsym'.


File: maxima.info,  Node: Tensoranalysis,  Next: Tensoren in gekrümmten Räumen,  Prev: Tensorsymmetrien,  Up: Funktionen und Variablen für itensor

20.2.2.3 Tensoranalysis
.......................

 -- Funktion: diff (<expr>, <v_1>, <n_1>, <v_2>, <n_2>, ...)

     Ist die gleichnamige Funktion 'diff' für die Differentiation einer
     tensoriellen Größe.  'diff' ist für das Paket 'itensor' erweitert.
     Die tensorielle Größe <expr> wird <n_1>-mal nach der Variablen
     <v_1>, <n_2> nach der Variablen <v_2>, ... abgeleitet.  Die
     Argumente 'v_1' können ganze Zahlen von '1', ..., 'dim' sein.  In
     diesem Fall bezeichnen die ganzen Zahlen der Reihe nach die
     Indizes, die in der Optionsvariablen 'vect_coords' abgelegt sind.
     'dim' ist die Dimension der tensoriellen Größen.

     Weiterhin erlaubt die erweiterte Funktion 'diff' die Berechnung von
     Ableitungen nach indizierten Variablen.  So können Ausdrücke, die
     den Metriktensor und seine Ableitungen enthalten, nach dem
     Metriktensor und seinen Ableitungen abgeleitet werden.

     Beispiele:

          (%i1) load(itensor)$

          (%i2) depends(v,t);
          (%o2)                        [v(t)]
          (%i3) ishow(diff(v([i,j],[k])^2, t,1))$
                                    k    d    k
          (%t3)                  2 v    (-- (v   ))
                                    i j  dt   i j
          (%i4) ishow(diff(v([i,j],[k])^2, t,2))$
                                 2
                           k    d     k          d    k    2
          (%t4)         2 v    (--- (v   )) + 2 (-- (v   ))
                           i j    2   i j        dt   i j
                                dt

 -- Funktion: idiff (<expr>, <v_1>, [<n_1>, [<v_2>, <n_2>] ...])

     'idiff' führt Ableitungen nach den Koordinaten einer tensoriellen
     Größe aus.  Im Unterschied dazu führt die Funktion 'diff'
     Ableitungen nach den unabhängigen Variablen aus.  Eine tensorielle
     Größe erhält zusätzlich den Index <v_1>, der die Ableitung
     bezeichnet.  Mehrfache Indizes für Ableitungen werden sortiert,
     außer wenn die Optionsvariable 'iframe_flag' den Wert 'true' hat.

     'idiff' kann auch die Determinante des Metriktensors ableiten.
     Wird zum Beispiel der Optionsvariablen 'imetric' der Wert 'g'
     zugewiesen, dann hat das Kommando 'idiff(determinant(g), k)' das
     Ergebnis '2 * determinant(g) * ichr2([%i,k], [%i])', wobei die
     Dummy-Variable passend gewählt wird.

 -- Funktion: liediff (<v>, <ten>)

     Berechnet die Lie-Ableitung eines tensoriellen Ausdrucks <ten> für
     das Vektorfeld <v>.  Das Argument <ten> kann irgendeine tensorielle
     Größe sein.  Das Argument <v> ist der Name eines Vektorfeldes und
     wird ohne Indizes angegeben.

     Beispiel:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(liediff(v,a([i,j],[])*b([],[k],l)))$
                 k    %2            %2          %2
          (%t2) b   (v   a       + v   a     + v   a    )
                 ,l       i j,%2    ,j  i %2    ,i  %2 j

                                    %1  k        %1  k      %1  k
                                + (v   b      - b   v    + v   b   ) a
                                        ,%1 l    ,l  ,%1    ,l  ,%1   i j

 -- Funktion: rediff (<ten>)

     Wertet jedes Auftreten von Substantivformen der Funktion 'idiff' in
     dem tensoriellem Ausdruck <ten> aus.

 -- Funktion: undiff (<expr>)

     Gibt einen zum Argument <expr> äquivalenten Ausdruck zurück, in dem
     alle Ableitungen von indizierten Größen durch Substantivformen der
     Funktion 'idiff' ersetzt sind.

 -- Funktion: evundiff (<expr>)

     Ist äquivalent zur Ausführung der Funktion 'undiff', der die
     Funktionen 'ev' und 'rediff' nachfolgen.

     'evundiff' erlaubt die Auswertung von Ausdrücken, die nicht direkt
     in ihrer abgeleiteten Form ausgewertet werden können.  So führt das
     folgende Beispiel zu einer Fehlermeldung:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) icurvature([i,j,k],[l],m);
          Maxima encountered a Lisp error:

           Error in $ICURVATURE [or a callee]:
           $ICURVATURE [or a callee] requires less than three arguments.

          Automatically continuing.
          To reenable the Lisp debugger set *debugger-hook* to nil.

     Wird jedoch 'icurvature' in der Substantivform verwendet, kann der
     Ausdruck mit 'evundiff' ausgewertet werden:

          (%i3) ishow('icurvature([i,j,k],[l],m))$
                                                   l
          (%t3)                          icurvature
                                                   i j k,m
          (%i4) ishow(evundiff(%))$
                       l              l         %1           l           %1
          (%t4) - ichr2        - ichr2     ichr2      - ichr2       ichr2
                       i k,j m        %1 j      i k,m        %1 j,m      i k

                       l              l         %1           l           %1
                + ichr2        + ichr2     ichr2      + ichr2       ichr2
                       i j,k m        %1 k      i j,m        %1 k,m      i j

     Um Christoffel-Symbole abzuleiten, wird die Funktion 'evundiff'
     nicht benötigt:

          (%i5) imetric(g);
          (%o5)                                done
          (%i6) ishow(ichr2([i,j],[k],l))$
                 k %3
                g     (g         - g         + g        )
                        j %3,i l    i j,%3 l    i %3,j l
          (%t6) -----------------------------------------
                                    2

                                   k %3
                                  g     (g       - g       + g      )
                                   ,l     j %3,i    i j,%3    i %3,j
                                + -----------------------------------
                                                   2

 -- Funktion: flush (<expr>, <tensor_1>, <tensor_2>, ...)

     Alle tensoriellen Größen <tensor_i> die im Ausdruck <expr>
     auftreten und keine Ableitungen haben, werden zu Null gesetzt.

 -- Funktion: flushd (<expr>, <tensor_1>, <tensor_2>, ...)

     Alle tensoriellen Größen <tensor_i> die im Ausdruck <expr>
     auftreten und Ableitungen haben, werden zu Null gesetzt.

 -- Funktion: flushnd (<expr>, <tensor>, <n>)

     Setzt alle Ableitungen der tensoriellen Größe <tensor> die im
     Ausdruck <expr> auftritt und <n> oder mehr Ableitungen hat, auf den
     Wert Null.

     Beispiele:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(a([i],[J,r],k,r)+a([i],[j,r,s],k,r,s))$
                                          J r      j r s
          (%t2)                          a      + a
                                          i,k r    i,k r s
          (%i3) ishow(flushnd(%,a,3))$
                                               J r
          (%t3)                               a
                                               i,k r

 -- Funktion: coord (<tensor_1>, <tensor_2>, ...)
 -- Systemvariable: coord

     Gibt der tensoriellen Größe <tensor_i> die Eigenschaft, dass die
     kovariante Ableitung eines Vektors mit dem Namen <tensor_i> das
     Ergebnis Kronecker-Delta hat.

     'coord' ist auch eine Systemvariable, die alle tensoriellen Größen
     enthält, die mit der Funktion 'coord' die Eigenschaft der
     kovarianten Ableitung erhalten haben.

     Beispiel:

          (%i1) coord(x);
          (%o1)                         done
          (%i2) idiff(x([],[i]),j);
          (%o2)                   kdelta([j], [i])
          (%i3) coord;
          (%o3)                          [x]

 -- Funktion: remcoord (<tensor_1>, <tensor_2>, ...)
 -- Funktion: remcoord (all)

     Entfernt die mit der Funktion 'coord' definierte Eigenschaft für
     die tensoriellen Größen <tensor_i>.  Das Kommando 'remcoord(all)'
     entfernt diese Eigenschaft für alle tensoriellen Größen.

 -- Funktion: makebox (<expr>, <name>)

     Zeigt das Argument <expr> auf die gleiche Weise an wie die Funktion
     'ishow' mit dem Unterschied, dass der dâAlembert-Operator <name>
     im Ausdruck durch '[]' ersetzt wird.

     Beispiel:

          (%i1) makebox(g([],[i,j])*p([m],[n],i,j),g);
          (%o1)                     []p([m], [n])

 -- Funktion: conmetderiv (<expr>, <tensor>)

     Vereinfacht Ausdrücke, die kovariante und kontravariante
     Ableitungen des Metriktensors enthalten.  'conmetderiv' kann zum
     Beispiel die Ableitungen des kontravarianten Metriktensors in
     Beziehung zu den Christoffel-Symbolen setzen:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(g([],[a,b],c))$
                                                a b
          (%t2)                                g
                                                ,c
          (%i3) ishow(conmetderiv(%,g))$
                                   %1 b      a       %1 a      b
          (%t3)                 - g     ichr2     - g     ichr2
                                             %1 c              %1 c

 -- Funktion: simpmetderiv (<expr>)
 -- Funktion: simpmetderiv (<expr>[, <stop>])

     Vereinfacht Ausdrücke die Produkte von Ableitungen des
     Metriktensors enthalten.  Im besonderen erkennt 'simpmetderiv' die
     folgenden Identitäten:

             ab        ab           ab                 a
            g   g   + g   g     = (g   g  )   = (kdelta )   = 0
             ,d  bc        bc,d         bc ,d          c ,d

     daher ist

             ab          ab
            g   g   = - g   g
             ,d  bc          bc,d

     und

            ab          ab
           g   g     = g   g
            ,j  ab,i    ,i  ab,j

     was aus den Symmetrien der Christoffel-Symbole folgt.

     Die Funktion 'simpmetderiv' akzeptiert einen optionalen Parameter
     <stop>.  Ist dieser vorhanden, stoppt die Funktion nach der ersten
     erfolgreichen Substitution in einem Produkt.  'simpmetderiv'
     beachtet ferner die Optionsvariable 'flipflag', welche die Ordnung
     der Indizes kontrolliert.

     Siehe auch 'weyl.dem' für Beispiele der Funktionen 'simpmetderiv'
     und 'conmetderiv', die die Vereinfachung des Weyl-Tensors zeigen.

     Beispiel:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) imetric(g);
          (%o2)                                done
          (%i3) ishow(g([],[a,b])*g([],[b,c])*g([a,b],[],d)*g([b,c],[],e))$
                                       a b  b c
          (%t3)                       g    g    g      g
                                                 a b,d  b c,e
          (%i4) ishow(canform(%))$

          errexp1 has improper indices
           -- an error.  Quitting.  To debug this try debugmode(true);
          (%i5) ishow(simpmetderiv(%))$
                                       a b  b c
          (%t5)                       g    g    g      g
                                                 a b,d  b c,e
          (%i6) flipflag:not flipflag;
          (%o6)                                true
          (%i7) ishow(simpmetderiv(%th(2)))$
                                         a b  b c
          (%t7)                         g    g    g    g
                                         ,d   ,e   a b  b c
          (%i8) flipflag:not flipflag;
          (%o8)                                false
          (%i9) ishow(simpmetderiv(%th(2),stop))$
                                         a b  b c
          (%t9)                       - g    g    g      g
                                              ,e   a b,d  b c
          (%i10) ishow(contract(%))$
                                              b c
          (%t10)                           - g    g
                                              ,e   c b,d

 -- Funktion: flush1deriv (<expr>, <tensor>)

     Setzt alle tensoriellen Größen, die genau einen Ableitungsindex
     haben, auf den Wert Null.

 -- Optionsvariable: vect_coords
     Standardwert: 'false'

     Tensoren können durch Angabe von ganzen Zahlen nach den einzelnen
     Komponenten abgeleitet werden.  In diesem Fall bezeichnen die
     ganzen Zahlen der Reihe nach die Indizes, die in der
     Optionsvariablen 'vect_coords' abgelegt sind.


File: maxima.info,  Node: Tensoren in gekrümmten Räumen,  Next: Begleitende Vielbeine,  Prev: Tensoranalysis,  Up: Funktionen und Variablen für itensor

20.2.2.4 Tensoren in gekrümmten Räumen
......................................

 -- Funktion: imetric (<g>)
 -- Systemvariable: imetric

     Spezifiziert die Metrik, indem der Variablen 'imetric' der Wert 'g'
     zugewiesen wird.  Die Eigenschaften für die Verjüngung von Tensoren
     werden mit den Kommandos 'defcon(<g>)' und 'defcon(<g>, <g>,
     kdelta)' initialisiert.

 -- Funktion: idim (<n>)

     Die Funktion 'idim' setzt die Dimension der Metrik zu <n>.  Die
     Variable 'dim' auf den Wert <n> gesetzt und die antisymmetrischen
     Eigenschaften des Levi-Civita-Symbols für die Dimension <n> werden
     initialisiert.

 -- Funktion: ichr1 ([<i>, <j>, <k>])

     Gibt das Christoffel-Symbol der ersten Art zurück, das definiert
     ist als

                 (g      + g      - g     )/2 .
                   ik,j     jk,i     ij,k

     Um das Christoffel-Symbol für eine spezielle Metrik auszuwerten,
     muss der Optionsvariablen 'imetric' ein Wert zugewiesen werden.
     Siehe dazu das Beispiel zu 'ichr2'.

 -- Funktion: ichr2 ([<i>, <j>], [<k>])

     Gibt das Christoffel-Symbol der zweiten Art zurück, das definiert
     ist als

                                 ks
             ichr2([i,j],[k]) = g    (g      + g      - g     )/2
                                       is,j     js,i     ij,s

 -- Funktion: icurvature ([<i>, <j>, <k>], [<h>])

     Gibt den Riemannschen Krümmungstensor in einer Darstellung mit
     Christoffel-Symbolen zurück:

                      h             h            h         %1         h
            icurvature     = - ichr2      - ichr2     ichr2    + ichr2
                      i j k         i k,j        %1 j      i k        i j,k
                                      h          %1
                               + ichr2      ichr2
                                      %1 k       i j

 -- Funktion: covdiff (<expr>, <v_1>, <v_2>, ...)

     Gibt die kovariante Ableitung des Ausdruck <expr> nach den
     Variablen <v_i> in einer Darstellung mit Christoffel-Symbolen der
     zweiten Art 'ichr2' zurück.  Um den erhaltenen Ausdruck
     auszuwerten, kann das Kommando 'ev(<expr>, ichr2)'.

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) entertensor()$
          Enter tensor name: a;
          Enter a list of the covariant indices: [i,j];
          Enter a list of the contravariant indices: [k];
          Enter a list of the derivative indices: [];
                                                k
          (%t2)                                a
                                                i j
          (%i3) ishow(covdiff(%,s))$
                       k         %1     k         %1     k
          (%t3)     - a     ichr2    - a     ichr2    + a
                       i %1      j s    %1 j      i s    i j,s

                       k     %1
                + ichr2     a
                       %1 s  i j
          (%i4) imetric:g;
          (%o4)                                  g
          (%i5) ishow(ev(%th(2),ichr2))$
                   %1 %4  k
                  g      a     (g       - g       + g      )
                          i %1   s %4,j    j s,%4    j %4,s
          (%t5) - ------------------------------------------
                                      2
              %1 %3  k
             g      a     (g       - g       + g      )
                     %1 j   s %3,i    i s,%3    i %3,s
           - ------------------------------------------
                                 2
              k %2  %1
             g     a    (g        - g        + g       )
                    i j   s %2,%1    %1 s,%2    %1 %2,s     k
           + ------------------------------------------- + a
                                  2                         i j,s
          (%i6)

 -- Funktion: lorentz_gauge (<expr>)

     Wendet die Lorenz-Eichung an, indem alle indizierten Größen in
     <expr> zu Null gesetzt werden, die einen zu einem kontravarianten
     Index identischen Ableitungsindex haben.

 -- Funktion: igeodesic_coords (<expr>, <name>)

     Bewirkt, dass nicht abgeleitete Christoffel-Symbole und erste
     Ableitungen des Metriktensors im Ausdruck <expr> verschwinden.  Das
     Argument <name> bezeichnet die Metrik <name>, wenn im Ausdruck
     <expr> vorhanden und die Christoffel-Symbole werden mit <ichr1> und
     <ichr2> bezeichnet.

     Beispiele:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(icurvature([r,s,t],[u]))$
                       u            u         %1         u
          (%t2) - ichr2      - ichr2     ichr2    + ichr2
                       r t,s        %1 s      r t        r s,t

                                                        u         %1
                                                 + ichr2     ichr2
                                                        %1 t      r s
          (%i3) ishow(igeodesic_coords(%,ichr2))$
                                           u            u
          (%t3)                       ichr2      - ichr2
                                           r s,t        r t,s
          (%i4) ishow(igeodesic_coords(icurvature([r,s,t],[u]),ichr2)+
                      igeodesic_coords(icurvature([s,t,r],[u]),ichr2)+
                      igeodesic_coords(icurvature([t,r,s],[u]),ichr2))$
                       u            u            u            u
          (%t4) - ichr2      + ichr2      + ichr2      - ichr2
                       t s,r        t r,s        s t,r        s r,t

                                                       u            u
                                                - ichr2      + ichr2
                                                       r t,s        r s,t
          (%i5) canform(%);
          (%o5)                                  0


File: maxima.info,  Node: Begleitende Vielbeine,  Next: Torsion und Nichtmetrizität,  Prev: Tensoren in gekrümmten Räumen,  Up: Funktionen und Variablen für itensor

20.2.2.5 Begleitende Vielbeine
..............................

Maxima now has the ability to perform calculations using moving frames.
These can be orthonormal frames (tetrads, vielbeins) or an arbitrary
frame.

To use frames, you must first set 'iframe_flag' to 'true'.  This causes
the Christoffel-symbols, 'ichr1' and 'ichr2', to be replaced by the more
general frame connection coefficients 'icc1' and 'icc2' in calculations.
Speficially, the behavior of 'covdiff' and 'icurvature' is changed.

The frame is defined by two tensors: the inverse frame field ('ifri',
the dual basis tetrad), and the frame metric 'ifg'.  The frame metric is
the identity matrix for orthonormal frames, or the Lorentz metric for
orthonormal frames in Minkowski spacetime.  The inverse frame field
defines the frame base (unit vectors).  Contraction properties are
defined for the frame field and the frame metric.

When 'iframe_flag' is true, many 'itensor' expressions use the frame
metric 'ifg' instead of the metric defined by 'imetric' for raising and
lowerind indices.

IMPORTANT: Setting the variable 'iframe_flag' to 'true' does NOT
undefine the contraction properties of a metric defined by a call to
'defcon' or 'imetric'.  If a frame field is used, it is best to define
the metric by assigning its name to the variable 'imetric' and NOT
invoke the 'imetric' function.

Maxima uses these two tensors to define the frame coefficients ('ifc1'
and 'ifc2') which form part of the connection coefficients ('icc1' and
'icc2'), as the following example demonstrates:

     (%i1) load(itensor);
     (%o1)      /share/tensor/itensor.lisp
     (%i2) iframe_flag:true;
     (%o2)                                true
     (%i3) ishow(covdiff(v([],[i]),j))$
                                    i        i     %1
     (%t3)                         v   + icc2     v
                                    ,j       %1 j
     (%i4) ishow(ev(%,icc2))$
                                    %1     i       i
     (%t4)                         v   ifc2     + v
                                           %1 j    ,j
     (%i5) ishow(ev(%,ifc2))$
                               %1    i %2                i
     (%t5)                    v   ifg     ifc1        + v
                                              %1 j %2    ,j
     (%i6) ishow(ev(%,ifc1))$
                 %1    i %2
                v   ifg     (ifb        - ifb        + ifb       )
                                j %2 %1      %2 %1 j      %1 j %2     i
     (%t6)      -------------------------------------------------- + v
                                        2                             ,j
     (%i7) ishow(ifb([a,b,c]))$
                                                        %3    %4
     (%t7)               (ifri        - ifri       ) ifr   ifr
                              a %3,%4       a %4,%3     b     c

An alternate method is used to compute the frame bracket ('ifb') if the
'iframe_bracket_form' flag is set to 'false':


     (%i8) block([iframe_bracket_form:false],ishow(ifb([a,b,c])))$
                                     %6    %5        %5      %6
     (%t8)              ifri     (ifr   ifr     - ifr     ifr  )
                            a %5     b     c,%6      b,%6    c

 -- Optionsvariable: iframe_flag
     Standardwert: 'false'

     To use frames, you must first set 'iframe_flag' to 'true'.  This
     causes the Christoffel-symbols, 'ichr1' and 'ichr2', to be replaced
     by the more general frame connection coefficients 'icc1' and 'icc2'
     in calculations.  Speficially, the behavior of 'covdiff' and
     'icurvature' is changed.

     The frame is defined by two tensors: the inverse frame field
     ('ifri', the dual basis tetrad), and the frame metric 'ifg'.  The
     frame metric is the identity matrix for orthonormal frames, or the
     Lorentz metric for orthonormal frames in Minkowski spacetime.  The
     inverse frame field defines the frame base (unit vectors).
     Contraction properties are defined for the frame field and the
     frame metric.

     When 'iframe_flag' is true, many 'itensor' expressions use the
     frame metric 'ifg' instead of the metric defined by 'imetric' for
     raising and lowerind indices.

     IMPORTANT: Setting the variable 'iframe_flag' to 'true' does NOT
     undefine the contraction properties of a metric defined by a call
     to 'defcon' or 'imetric'.  If a frame field is used, it is best to
     define the metric by assigning its name to the variable 'imetric'
     and NOT invoke the 'imetric' function.

 -- Function: iframes ()

     Since in this version of Maxima, contraction identities for 'ifr'
     and 'ifri' are always defined, as is the frame bracket ('ifb'),
     this function does nothing.

 -- Variable: ifb

     The frame bracket.  The contribution of the frame metric to the
     connection coefficients is expressed using the frame bracket:

                    - ifb      + ifb      + ifb
                         c a b      b c a      a b c
          ifc1    = --------------------------------
              abc                  2

     The frame bracket itself is defined in terms of the frame field and
     frame metric.  Two alternate methods of computation are used
     depending on the value of 'frame_bracket_form'.  If true (the
     default) or if the 'itorsion_flag' is 'true':

                    d      e                                      f
          ifb =  ifr    ifr   (ifri      - ifri      - ifri    itr   )
             abc    b      c       a d,e       a e,d       a f    d e

     Otherwise:

                       e      d        d      e
          ifb    = (ifr    ifr    - ifr    ifr   ) ifri
             abc       b      c,e      b,e    c        a d

 -- Variable: icc1

     Connection coefficients of the first kind.  In 'itensor', defined
     as

          icc1    = ichr1    - ikt1    - inmc1
              abc        abc       abc        abc

     In this expression, if 'iframe_flag' is true, the
     Christoffel-symbol 'ichr1' is replaced with the frame connection
     coefficient 'ifc1'.  If 'itorsion_flag' is 'false', 'ikt1' will be
     omitted.  It is also omitted if a frame base is used, as the
     torsion is already calculated as part of the frame bracket.
     Lastly, of 'inonmet_flag' is 'false', 'inmc1' will not be present.

 -- Variable: icc2

     Connection coefficients of the second kind.  In 'itensor', defined
     as

              c         c        c         c
          icc2   = ichr2   - ikt2   - inmc2
              ab        ab       ab        ab

     In this expression, if 'iframe_flag' is true, the
     Christoffel-symbol 'ichr2' is replaced with the frame connection
     coefficient 'ifc2'.  If 'itorsion_flag' is 'false', 'ikt2' will be
     omitted.  It is also omitted if a frame base is used, as the
     torsion is already calculated as part of the frame bracket.
     Lastly, of 'inonmet_flag' is 'false', 'inmc2' will not be present.

 -- Variable: ifc1

     Frame coefficient of the first kind (also known as Ricci-rotation
     coefficients.)  This tensor represents the contribution of the
     frame metric to the connection coefficient of the first kind.
     Defined as:

                    - ifb      + ifb      + ifb
                         c a b      b c a      a b c
          ifc1    = --------------------------------
              abc                   2

 -- Variable: ifc2

     Frame coefficient of the first kind.  This tensor represents the
     contribution of the frame metric to the connection coefficient of
     the first kind.  Defined as a permutation of the frame bracket
     ('ifb') with the appropriate indices raised and lowered as
     necessary:

              c       cd
          ifc2   = ifg   ifc1
              ab             abd

 -- Variable: ifr

     The frame field.  Contracts with the inverse frame field ('ifri')
     to form the frame metric ('ifg').

 -- Variable: ifri

     The inverse frame field.  Specifies the frame base (dual basis
     vectors).  Along with the frame metric, it forms the basis of all
     calculations based on frames.

 -- Variable: ifg

     The frame metric.  Defaults to 'kdelta', but can be changed using
     'components'.

 -- Variable: ifgi

     The inverse frame metric.  Contracts with the frame metric ('ifg')
     to 'kdelta'.

 -- Option variable: iframe_bracket_form
     Default value: 'true'

     Specifies how the frame bracket ('ifb') is computed.


File: maxima.info,  Node: Torsion und Nichtmetrizität,  Next: Graßmann-Algebra,  Prev: Begleitende Vielbeine,  Up: Funktionen und Variablen für itensor

20.2.2.6 Torsion und Nichtmetrizität
....................................

Maxima can now take into account torsion and nonmetricity.  When the
flag 'itorsion_flag' is set to 'true', the contribution of torsion is
added to the connection coefficients.  Similarly, when the flag
'inonmet_flag' is true, nonmetricity components are included.

 -- Variable: inm

     The nonmetricity vector.  Conformal nonmetricity is defined through
     the covariant derivative of the metric tensor.  Normally zero, the
     metric tensor's covariant derivative will evaluate to the following
     when 'inonmet_flag' is set to 'true':

          g     =- g  inm
           ij;k     ij   k

 -- Variable: inmc1

     Covariant permutation of the nonmetricity vector components.
     Defined as

                     g   inm  - inm  g   - g   inm
                      ab    c      a  bc    ac    b
          inmc1    = ------------------------------
               abc                 2

     (Substitute 'ifg' in place of 'g' if a frame metric is used.)

 -- Variable: inmc2

     Contravariant permutation of the nonmetricity vector components.
     Used in the connection coefficients if 'inonmet_flag' is 'true'.
     Defined as:

                                c         c         cd
                    -inm  kdelta  - kdelta  inm  + g   inm  g
               c        a       b         a    b          d  ab
          inmc2   = -------------------------------------------
               ab                        2

     (Substitute 'ifg' in place of 'g' if a frame metric is used.)

 -- Variable: ikt1

     Covariant permutation of the torsion tensor (also known as
     contorsion).  Defined as:

                            d           d       d
                    -g   itr  - g    itr   - itr   g
                      ad    cb    bd    ca      ab  cd
          ikt1    = ----------------------------------
              abc                   2

     (Substitute 'ifg' in place of 'g' if a frame metric is used.)

 -- Variable: ikt2

     Contravariant permutation of the torsion tensor (also known as
     contorsion).  Defined as:

              c     cd
          ikt2   = g   ikt1
              ab           abd

     (Substitute 'ifg' in place of 'g' if a frame metric is used.)

 -- Variable: itr

     The torsion tensor.  For a metric with torsion, repeated covariant
     differentiation on a scalar function will not commute, as
     demonstrated by the following example:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) imetric:g;
          (%o2)                                  g
          (%i3) covdiff( covdiff( f( [], []), i), j)
                                - covdiff( covdiff( f( [], []), j), i)$
          (%i4) ishow(%)$
                                             %4              %2
          (%t4)                    f    ichr2    - f    ichr2
                                    ,%4      j i    ,%2      i j
          (%i5) canform(%);
          (%o5)                                  0
          (%i6) itorsion_flag:true;
          (%o6)                                true
          (%i7) covdiff( covdiff( f( [], []), i), j)
                                - covdiff( covdiff( f( [], []), j), i)$
          (%i8) ishow(%)$
                                     %8             %6
          (%t8)             f    icc2    - f    icc2    - f     + f
                             ,%8     j i    ,%6     i j    ,j i    ,i j
          (%i9) ishow(canform(%))$
                                             %1             %1
          (%t9)                     f    icc2    - f    icc2
                                     ,%1     j i    ,%1     i j
          (%i10) ishow(canform(ev(%,icc2)))$
                                             %1             %1
          (%t10)                    f    ikt2    - f    ikt2
                                     ,%1     i j    ,%1     j i
          (%i11) ishow(canform(ev(%,ikt2)))$
                                %2 %1                    %2 %1
          (%t11)          f    g      ikt1       - f    g      ikt1
                           ,%2            i j %1    ,%2            j i %1
          (%i12) ishow(factor(canform(rename(expand(ev(%,ikt1))))))$
                                     %3 %2            %1       %1
                               f    g      g      (itr    - itr   )
                                ,%3         %2 %1     j i      i j
          (%t12)               ------------------------------------
                                                2
          (%i13) decsym(itr,2,1,[anti(all)],[]);
          (%o13)                               done
          (%i14) defcon(g,g,kdelta);
          (%o14)                               done
          (%i15) subst(g,nounify(g),%th(3))$
          (%i16) ishow(canform(contract(%)))$
                                                     %1
          (%t16)                           - f    itr
                                              ,%1    i j


File: maxima.info,  Node: Graßmann-Algebra,  Next: Exportiere als TeX,  Prev: Torsion und Nichtmetrizität,  Up: Funktionen und Variablen für itensor

20.2.2.7 Graßmann-Algebra
.........................

The 'itensor' package can perform operations on totally antisymmetric
covariant tensor fields.  A totally antisymmetric tensor field of rank
(0,L) corresponds with a differential L-form.  On these objects, a
multiplication operation known as the exterior product, or wedge
product, is defined.

Unfortunately, not all authors agree on the definition of the wedge
product.  Some authors prefer a definition that corresponds with the
notion of antisymmetrization: in these works, the wedge product of two
vector fields, for instance, would be defined as

                 a a  - a a
                  i j    j i
      a  /\ a  = -----------
       i     j        2

More generally, the product of a p-form and a q-form would be defined as

                            1     k1..kp l1..lq
     A       /\ B       = ------ D              A       B
      i1..ip     j1..jq   (p+q)!  i1..ip j1..jq  k1..kp  l1..lq

where 'D' stands for the Kronecker-delta.

Other authors, however, prefer a "geometric" definition that corresponds
with the notion of the volume element:

     a  /\ a  = a a  - a a
      i     j    i j    j i

and, in the general case

                            1    k1..kp l1..lq
     A       /\ B       = ----- D              A       B
      i1..ip     j1..jq   p! q!  i1..ip j1..jq  k1..kp  l1..lq

Since 'itensor' is a tensor algebra package, the first of these two
definitions appears to be the more natural one.  Many applications,
however, utilize the second definition.  To resolve this dilemma, a flag
has been implemented that controls the behavior of the wedge product: if
'igeowedge_flag' is 'false' (the default), the first, "tensorial"
definition is used, otherwise the second, "geometric" definition will be
applied.

 -- Operator: ~

     The wedge product operator is denoted by the tilde '~'.  This is a
     binary operator.  Its arguments should be expressions involving
     scalars, covariant tensors of rank one, or covariant tensors of
     rank 'l' that have been declared antisymmetric in all covariant
     indices.

     The behavior of the wedge product operator is controlled by the
     'igeowedge_flag' flag, as in the following example:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(a([i])~b([j]))$
                                           a  b  - b  a
                                            i  j    i  j
          (%t2)                            -------------
                                                 2
          (%i3) decsym(a,2,0,[anti(all)],[]);
          (%o3)                                done
          (%i4) ishow(a([i,j])~b([k]))$
                                    a    b  + b  a    - a    b
                                     i j  k    i  j k    i k  j
          (%t4)                     ---------------------------
                                                 3
          (%i5) igeowedge_flag:true;
          (%o5)                                true
          (%i6) ishow(a([i])~b([j]))$
          (%t6)                            a  b  - b  a
                                            i  j    i  j
          (%i7) ishow(a([i,j])~b([k]))$
          (%t7)                     a    b  + b  a    - a    b
                                     i j  k    i  j k    i k  j

 -- Operator: |

     The vertical bar '|' denotes the "contraction with a vector" binary
     operation.  When a totally antisymmetric covariant tensor is
     contracted with a contravariant vector, the result is the same
     regardless which index was used for the contraction.  Thus, it is
     possible to define the contraction operation in an index-free
     manner.

     In the 'itensor' package, contraction with a vector is always
     carried out with respect to the first index in the literal sorting
     order.  This ensures better simplification of expressions involving
     the '|' operator.  For instance:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) decsym(a,2,0,[anti(all)],[]);
          (%o2)                                done
          (%i3) ishow(a([i,j],[])|v)$
                                              %1
          (%t3)                              v   a
                                                  %1 j
          (%i4) ishow(a([j,i],[])|v)$
                                               %1
          (%t4)                             - v   a
                                                   %1 j

     Note that it is essential that the tensors used with the '|'
     operator be declared totally antisymmetric in their covariant
     indices.  Otherwise, the results will be incorrect.

 -- Function: extdiff (<expr>, <i>)

     Computes the exterior derivative of <expr> with respect to the
     index <i>.  The exterior derivative is formally defined as the
     wedge product of the partial derivative operator and a differential
     form.  As such, this operation is also controlled by the setting of
     'igeowedge_flag'.  For instance:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) ishow(extdiff(v([i]),j))$
                                            v    - v
                                             j,i    i,j
          (%t2)                             -----------
                                                 2
          (%i3) decsym(a,2,0,[anti(all)],[]);
          (%o3)                                done
          (%i4) ishow(extdiff(a([i,j]),k))$
                                     a      - a      + a
                                      j k,i    i k,j    i j,k
          (%t4)                      ------------------------
                                                3
          (%i5) igeowedge_flag:true;
          (%o5)                                true
          (%i6) ishow(extdiff(v([i]),j))$
          (%t6)                             v    - v
                                             j,i    i,j
          (%i7) ishow(extdiff(a([i,j]),k))$
          (%t7)                    - (a      - a      + a     )
                                       k j,i    k i,j    j i,k

 -- Function: hodge (<expr>)

     Compute the Hodge-dual of <expr>.  For instance:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) imetric(g);
          (%o2)                            done
          (%i3) idim(4);
          (%o3)                            done
          (%i4) icounter:100;
          (%o4)                             100
          (%i5) decsym(A,3,0,[anti(all)],[])$

          (%i6) ishow(A([i,j,k],[]))$
          (%t6)                           A
                                           i j k
          (%i7) ishow(canform(hodge(%)))$
                                    %1 %2 %3 %4
                         levi_civita            g        A
                                                 %1 %102  %2 %3 %4
          (%t7)          -----------------------------------------
                                             6
          (%i8) ishow(canform(hodge(%)))$
                           %1 %2 %3 %8            %4 %5 %6 %7
          (%t8) levi_civita            levi_civita            g
                                                               %1 %106
                                       g        g        g      A         /6
                                        %2 %107  %3 %108  %4 %8  %5 %6 %7
          (%i9) lc2kdt(%)$

          (%i10) %,kdelta$

          (%i11) ishow(canform(contract(expand(%))))$
          (%t11)                     - A
                                        %106 %107 %108

 -- Option variable: igeowedge_flag
     Default value: 'false'

     Controls the behavior of the wedge product and exterior derivative.
     When set to 'false' (the default), the notion of differential forms
     will correspond with that of a totally antisymmetric covariant
     tensor field.  When set to 'true', differential forms will agree
     with the notion of the volume element.


File: maxima.info,  Node: Exportiere als TeX,  Next: Schnittstelle zum Paket ctensor,  Prev: Graßmann-Algebra,  Up: Funktionen und Variablen für itensor

20.2.2.8 Exportiere als TeX
...........................

The 'itensor' package provides limited support for exporting tensor
expressions to TeX. Since 'itensor' expressions appear as function
calls, the regular Maxima 'tex' command will not produce the expected
output.  You can try instead the 'tentex' command, which attempts to
translate tensor expressions into appropriately indexed TeX objects.

 -- Function: tentex (<expr>)

     To use the 'tentex' function, you must first load 'tentex', as in
     the following example:

          (%i1) load(itensor)$
          (%i2) load(tentex)$
          (%i3) idummyx:m;
          (%o3)                                  m
          (%i4) ishow(icurvature([j,k,l],[i]))$
                      m1       i           m1       i           i
          (%t4)  ichr2    ichr2     - ichr2    ichr2     - ichr2
                      j k      m1 l        j l      m1 k        j l,k

                                                                i
                                                         + ichr2
                                                                j k,l
          (%i5) tentex(%)$
          $$\Gamma_{j\,k}^{m_1}\,\Gamma_{l\,m_1}^{i}-\Gamma_{j\,l}^{m_1}\,
           \Gamma_{k\,m_1}^{i}-\Gamma_{j\,l,k}^{i}+\Gamma_{j\,k,l}^{i}$$

     Note the use of the 'idummyx' assignment, to avoid the appearance
     of the percent sign in the TeX expression, which may lead to
     compile errors.

     NB: This version of the 'tentex' function is somewhat experimental.


File: maxima.info,  Node: Schnittstelle zum Paket ctensor,  Next: Reservierte Bezeichner,  Prev: Exportiere als TeX,  Up: Funktionen und Variablen für itensor

20.2.2.9 Schnittstelle zum Paket CTENSOR
........................................

Das Paket 'itensor' ermöglicht die Generierung von Maxima-Code, der im
Kontext des Paketes 'ctensor' ausgeführt werden kann.  Die Funktion
'ic_convert' erzeugt den Maxima-Code.

 -- Funktion: ic_convert (<eqn>)

     Konvertiert eine 'itensor'-Gleichung <eqn> in einen
     'ctensor'-Ausdruck.  Implizite Summen über Dummy-Indizes werden
     explizit ausgeführt und indizierte Größen werden in Arrays
     umgewandelt.  Die Indizes der Arrays sind in der Reihenfolge der
     kovarianten und dann der kontravarianten Indizes der indizierte
     Größe.  Die Ableitung einer indizierten Größe wird durch die
     Substantivform der Ableitung 'diff' nach der Variablen 'ct_coords'
     ersetzt, die den Index der Ableitung erhält.  Die
     Christoffel-Symbole 'ichr1' und 'ichr2' werden zu den Funktionen
     'lcs' und 'mcs' transformiert.  Hat 'metricconvert' den Wert
     'true', dann wird der Metriktensor mit zwei kovarianten Indizes
     durch 'lg' und mit zwei kontravarianten Indizes durch 'ug' ersetzt.
     Weiterhin werden 'do'-Schleifen für die Summation über die freien
     Indizes eingeführt.

     Beispiele:

          (%i1) load(itensor);
          (%o1)      /share/tensor/itensor.lisp
          (%i2) eqn:ishow(t([i,j],[k])=f([],[])*g([l,m],[])*a([],[m],j)
                *b([i],[l,k]))$
                                       k        m   l k
          (%t2)                       t    = f a   b    g
                                       i j      ,j  i    l m
          (%i3) ic_convert(eqn);
          (%o3) for i thru dim do (for j thru dim do (
                 for k thru dim do
                  t        : f sum(sum(diff(a , ct_coords ) b
                   i, j, k                   m           j   i, l, k

           g    , l, 1, dim), m, 1, dim)))
            l, m
          (%i4) imetric(g);
          (%o4)                                done
          (%i5) metricconvert:true;
          (%o5)                                true
          (%i6) ic_convert(eqn);
          (%o6) for i thru dim do (for j thru dim do (
                 for k thru dim do
                  t        : f sum(sum(diff(a , ct_coords ) b
                   i, j, k                   m           j   i, l, k

           lg    , l, 1, dim), m, 1, dim)))
             l, m


File: maxima.info,  Node: Reservierte Bezeichner,  Prev: Schnittstelle zum Paket ctensor,  Up: Funktionen und Variablen für itensor

20.2.2.10 Reservierte Bezeichner
................................

Die folgenden Maxima Bezeichner werden im Paket 'itensor' intern genutzt
und sollten vom Nutzer nicht umdefiniert werden.

       Keyword    Comments
       ------------------------------------------
       indices2() Internal version of indices()
       conti      Lists contravariant indices
       covi       Lists covariant indices of a indexed object
       deri       Lists derivative indices of an indexed object
       name       Returns the name of an indexed object
       concan
       irpmon
       lc0
       _lc2kdt0
       _lcprod
       _extlc


File: maxima.info,  Node: Paket ctensor,  Next: Paket atensor,  Prev: Paket itensor,  Up: Tensoren

20.3 Paket CTENSOR
==================

* Menu:

* Einführung in ctensor::
* Funktionen und Variablen für ctensor::


File: maxima.info,  Node: Einführung in ctensor,  Next: Funktionen und Variablen für ctensor,  Prev: Paket ctensor,  Up: Paket ctensor

20.3.1 Einführung in CTENSOR
----------------------------

'ctensor' ist ein Paket, um mit den Komponenten eines Tensors zu
rechnen.  Das Paket wird mit dem Kommando 'load(ctensor)' geladen.  Zu
Beginn muss das Paket mit dem Kommando 'csetup' initialisiert werden.
Als erstes wird die Anzahl der Dimensionen angegeben.  Werden '2', '3'
oder '4' Dimensionen angegeben, dann erhalten die Koordinaten
standardmäßig die Bezeichnungen '[x,y]', '[x,y,z]' oder '[x,y,z,t]'.
Diese Bezeichnungen können geändert werden, indem der Optionsvariablen
'ct_coords' eine neue Liste mit den gewünschten Bezeichnungen zugewiesen
wird.

Danach wird eine Metrik eingegeben oder aus einer Datei geladen.  Die
Metrik wird in der Matrix 'lg' gespeichert.  Maxima berechnet die
inverse der Metrik und speichert diese in der Matrix 'ug' ab.  Maxima
bietet die Option an, alle Rechnungen in einer Reihenentwicklung
auszuführen.

Die folgende Sitzung zeigt ein Beispiel für die Initialisierung einer
sphärischen, symmetrischen Metrik, wie sie zum Beispiel im Falle der
Einsteinschen Vakuumgleichen verwendet wird.

Beispiel:

     (%i1) load(ctensor);
     (%o1)      /share/tensor/ctensor.mac
     (%i2) csetup();
     Enter the dimension of the coordinate system:
     4;
     Do you wish to change the coordinate names?
     n;
     Do you want to
     1. Enter a new metric?

     2. Enter a metric from a file?

     3. Approximate a metric with a Taylor series?
     1;

     Is the matrix  1. Diagonal  2. Symmetric  3. Antisymmetric  4. General
     Answer 1, 2, 3 or 4
     1;
     Row 1 Column 1:
     a;
     Row 2 Column 2:
     x^2;
     Row 3 Column 3:
     x^2*sin(y)^2;
     Row 4 Column 4:
     -d;

     Matrix entered.
     Enter functional dependencies with the DEPENDS function or 'N' if none
     depends([a,d],x);
     Do you wish to see the metric?
     y;
                               [ a  0       0        0  ]
                               [                        ]
                               [     2                  ]
                               [ 0  x       0        0  ]
                               [                        ]
                               [         2    2         ]
                               [ 0  0   x  sin (y)   0  ]
                               [                        ]
                               [ 0  0       0       - d ]
     (%o2)                                done
     (%i3) christof(mcs);
                                                 a
                                                  x
     (%t3)                          mcs        = ---
                                       1, 1, 1   2 a

                                                  1
     (%t4)                           mcs        = -
                                        1, 2, 2   x

                                                  1
     (%t5)                           mcs        = -
                                        1, 3, 3   x

                                                 d
                                                  x
     (%t6)                          mcs        = ---
                                       1, 4, 4   2 d

                                                   x
     (%t7)                          mcs        = - -
                                       2, 2, 1     a

                                                cos(y)
     (%t8)                         mcs        = ------
                                      2, 3, 3   sin(y)

                                                    2
                                               x sin (y)
     (%t9)                      mcs        = - ---------
                                   3, 3, 1         a

     (%t10)                   mcs        = - cos(y) sin(y)
                                 3, 3, 2

                                                 d
                                                  x
     (%t11)                         mcs        = ---
                                       4, 4, 1   2 a
     (%o11)                               done


File: maxima.info,  Node: Funktionen und Variablen für ctensor,  Prev: Einführung in ctensor,  Up: Paket ctensor

20.3.2 Funktionen und Variablen für CTENSOR
-------------------------------------------

20.3.2.1 Initialisierung
........................

 -- Funktion: csetup ()

     Mit der Funktion 'csetup' wird das Paket 'ctensor' initialisiert.
     Vom Nutzer werden die Angaben zu einer Metrik abgefragt.  Für ein
     Beispiel siehe *note Einführung in ctensor::.

 -- Funktion: cmetric (<dis>)
 -- Funktion: cmetric ()

     Die Funktion 'cmetric' berechnet die inverse der Metrik und führt
     weitere Initialisierungen für die Rechnung mit Tensoren aus.

     Hat die Optionsvariable 'cframe_flag' den Wert 'false', wird die
     inverse Metrik mit der vom Nutzer angegebenen Metrik berechnet, die
     in der Matrix 'lg' enthalten ist, und in der Matrix 'ug'
     abgespeichert.  Die Determinante der Metrik wird in der Variablen
     'gdet' abgelegt.  Ist die Metrik diagonal wird die Variable
     'diagmetric' entsprechend gesetzt.  Hat das optionale Argument
     <dis> einen von 'false' verschiedenen Wert wird die inverse Metrik
     ausgegeben.

     Hat die Optionsvariable 'cframe_flag' den Wert 'true', erwartet
     'cmetric', dass die Matrizen 'lfg' für die Metrik des bewegten
     Bezugssystems und 'fri' für die inverse dieser Metrik definiert
     sind.  Mit diesen Matrizen berechnet 'cmetric' dann die Werte der
     Matrizen 'fr' und die inverse 'ufg'.

 -- Function: ct_coordsys (<coordinate_system>, <extra_arg>)
 -- Function: ct_coordsys (<coordinate_system>)

     Sets up a predefined coordinate system and metric.  The argument
     <coordinate_system> can be one of the following symbols:

           SYMBOL             Dim Coordinates     Description/comments
           ------------------------------------------------------------------
           cartesian2d           2  [x,y]             Cartesian 2D coordinate
                                                      system
           polar                 2  [r,phi]           Polar coordinate system
           elliptic              2  [u,v]             Elliptic coord. system
           confocalelliptic      2  [u,v]             Confocal elliptic
                                                      coordinates
           bipolar               2  [u,v]             Bipolar coord. system
           parabolic             2  [u,v]             Parabolic coord. system
           cartesian3d           3  [x,y,z]           Cartesian 3D coordinate
                                                      system
           polarcylindrical      3  [r,theta,z]       Polar 2D with
                                                      cylindrical z
           ellipticcylindrical   3  [u,v,z]           Elliptic 2D with
                                                      cylindrical z
           confocalellipsoidal   3  [u,v,w]           Confocal ellipsoidal
           bipolarcylindrical    3  [u,v,z]           Bipolar 2D with
                                                      cylindrical z
           paraboliccylindrical  3  [u,v,z]           Parabolic 2D with
                                                      cylindrical z
           paraboloidal          3  [u,v,phi]         Paraboloidal coords.
           conical               3  [u,v,w]           Conical coordinates
           toroidal              3  [u,v,phi]         Toroidal coordinates
           spherical             3  [r,theta,phi]     Spherical coord. system
           oblatespheroidal      3  [u,v,phi]         Oblate spheroidal
                                                      coordinates
           oblatespheroidalsqrt  3  [u,v,phi]
           prolatespheroidal     3  [u,v,phi]         Prolate spheroidal
                                                      coordinates
           prolatespheroidalsqrt 3  [u,v,phi]
           ellipsoidal           3  [r,theta,phi]     Ellipsoidal coordinates
           cartesian4d           4  [x,y,z,t]         Cartesian 4D coordinate
                                                      system
           spherical4d           4  [r,theta,eta,phi] Spherical 4D coordinate
                                                      system
           exteriorschwarzschild 4  [t,r,theta,phi]   Schwarzschild metric
           interiorschwarzschild 4  [t,z,u,v]         Interior Schwarzschild
                                                      metric
           kerr_newman           4  [t,r,theta,phi]   Charged axially
                                                      symmetric metric

     'coordinate_system' can also be a list of transformation functions,
     followed by a list containing the coordinate variables.  For
     instance, you can specify a spherical metric as follows:

          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) ct_coordsys([r*cos(theta)*cos(phi),r*cos(theta)*sin(phi),
                             r*sin(theta),[r,theta,phi]]);
          (%o2)                                done
          (%i3) lg:trigsimp(lg);
                                     [ 1  0         0        ]
                                     [                       ]
                                     [     2                 ]
          (%o3)                      [ 0  r         0        ]
                                     [                       ]
                                     [         2    2        ]
                                     [ 0  0   r  cos (theta) ]
          (%i4) ct_coords;
          (%o4)                           [r, theta, phi]
          (%i5) dim;
          (%o5)                                  3

     Transformation functions can also be used when 'cframe_flag' is
     'true':

          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) cframe_flag:true;
          (%o2)                                true
          (%i3) ct_coordsys([r*cos(theta)*cos(phi),r*cos(theta)*sin(phi),
                r*sin(theta),[r,theta,phi]]);
          (%o3)                                done
          (%i4) fri;
          (%o4)
           [cos(phi)cos(theta) -cos(phi) r sin(theta) -sin(phi) r cos(theta)]
           [                                                                ]
           [sin(phi)cos(theta) -sin(phi) r sin(theta)  cos(phi) r cos(theta)]
           [                                                                ]
           [    sin(theta)           r cos(theta)                0          ]

          (%i5) cmetric();
          (%o5)                                false
          (%i6) lg:trigsimp(lg);
                                     [ 1  0         0        ]
                                     [                       ]
                                     [     2                 ]
          (%o6)                      [ 0  r         0        ]
                                     [                       ]
                                     [         2    2        ]
                                     [ 0  0   r  cos (theta) ]

     The optional argument <extra_arg> can be any one of the following:

     'cylindrical' tells 'ct_coordsys' to attach an additional
     cylindrical coordinate.

     'minkowski' tells 'ct_coordsys' to attach an additional coordinate
     with negative metric signature.

     'all' tells 'ct_coordsys' to call 'cmetric' and 'christof(false)'
     after setting up the metric.

     If the global variable 'verbose' is set to 'true', 'ct_coordsys'
     displays the values of 'dim', 'ct_coords', and either 'lg' or 'lfg'
     and 'fri', depending on the value of 'cframe_flag'.

 -- Function: init_ctensor ()

     Initializes the 'ctensor' package.

     The 'init_ctensor' function reinitializes the 'ctensor' package.
     It removes all arrays and matrices used by 'ctensor', resets all
     flags, resets 'dim' to 4, and resets the frame metric to the
     Lorentz-frame.

20.3.2.2 The tensors of curved space
....................................

The main purpose of the 'ctensor' package is to compute the tensors of
curved space(time), most notably the tensors used in general relativity.

When a metric base is used, 'ctensor' can compute the following tensors:

      lg  -- ug
        \      \
         lcs -- mcs -- ric -- uric
                   \      \       \
                    \      tracer - ein -- lein
                     \
                      riem -- lriem -- weyl
                          \
                           uriem

'ctensor' can also work using moving frames.  When 'cframe_flag' is set
to 'true', the following tensors can be calculated:

      lfg -- ufg
          \
      fri -- fr -- lcs -- mcs -- lriem -- ric -- uric
           \                       |  \      \       \
            lg -- ug               |   weyl   tracer - ein -- lein
                                   |\
                                   | riem
                                   |
                                   \uriem

 -- Function: christof (<dis>)

     A function in the 'ctensor' (component tensor) package.  It
     computes the Christoffel symbols of both kinds.  The argument <dis>
     determines which results are to be immediately displayed.  The
     Christoffel symbols of the first and second kinds are stored in the
     arrays 'lcs[i,j,k]' and 'mcs[i,j,k]' respectively and defined to be
     symmetric in the first two indices.  If the argument to 'christof'
     is 'lcs' or 'mcs' then the unique non-zero values of 'lcs[i,j,k]'
     or 'mcs[i,j,k]', respectively, will be displayed.  If the argument
     is 'all' then the unique non-zero values of 'lcs[i,j,k]' and
     'mcs[i,j,k]' will be displayed.  If the argument is 'false' then
     the display of the elements will not occur.  The array elements
     'mcs[i,j,k]' are defined in such a manner that the final index is
     contravariant.

 -- Function: ricci (<dis>)

     A function in the 'ctensor' (component tensor) package.  'ricci'
     computes the covariant (symmetric) components 'ric[i,j]' of the
     Ricci tensor.  If the argument <dis> is 'true', then the non-zero
     components are displayed.

 -- Function: uricci (<dis>)

     This function first computes the covariant components 'ric[i,j]' of
     the Ricci tensor.  Then the mixed Ricci tensor is computed using
     the contravariant metric tensor.  If the value of the argument
     <dis> is 'true', then these mixed components, 'uric[i,j]' (the
     index 'i' is covariant and the index 'j' is contravariant), will be
     displayed directly.  Otherwise, 'ricci(false)' will simply compute
     the entries of the array 'uric[i,j]' without displaying the
     results.

 -- Function: scurvature ()

     Returns the scalar curvature (obtained by contracting the Ricci
     tensor) of the Riemannian manifold with the given metric.

 -- Function: einstein (<dis>)

     A function in the 'ctensor' (component tensor) package.  'einstein'
     computes the mixed Einstein tensor after the Christoffel symbols
     and Ricci tensor have been obtained (with the functions 'christof'
     and 'ricci').  If the argument <dis> is 'true', then the non-zero
     values of the mixed Einstein tensor 'ein[i,j]' will be displayed
     where 'j' is the contravariant index.  The variable 'rateinstein'
     will cause the rational simplification on these components.  If
     'ratfac' is 'true' then the components will also be factored.

 -- Function: leinstein (<dis>)

     Covariant Einstein-tensor.  'leinstein' stores the values of the
     covariant Einstein tensor in the array 'lein'.  The covariant
     Einstein-tensor is computed from the mixed Einstein tensor 'ein' by
     multiplying it with the metric tensor.  If the argument <dis> is
     'true', then the non-zero values of the covariant Einstein tensor
     are displayed.

 -- Function: riemann (<dis>)

     A function in the 'ctensor' (component tensor) package.  'riemann'
     computes the Riemann curvature tensor from the given metric and the
     corresponding Christoffel symbols.  The following index conventions
     are used:

                          l      _l       _l       _l   _m    _l   _m
           R[i,j,k,l] =  R    = |      - |      + |    |   - |    |
                          ijk     ij,k     ik,j     mk   ij    mj   ik

     This notation is consistent with the notation used by the 'itensor'
     package and its 'icurvature' function.  If the optional argument
     <dis> is 'true', the non-zero components 'riem[i,j,k,l]' will be
     displayed.  As with the Einstein tensor, various switches set by
     the user control the simplification of the components of the
     Riemann tensor.  If 'ratriemann' is 'true', then rational
     simplification will be done.  If 'ratfac' is 'true' then each of
     the components will also be factored.

     If the variable 'cframe_flag' is 'false', the Riemann tensor is
     computed directly from the Christoffel-symbols.  If 'cframe_flag'
     is 'true', the covariant Riemann-tensor is computed first from the
     frame field coefficients.

 -- Function: lriemann (<dis>)

     Covariant Riemann-tensor ('lriem[]').

     Computes the covariant Riemann-tensor as the array 'lriem'.  If the
     argument <dis> is 'true', unique nonzero values are displayed.

     If the variable 'cframe_flag' is 'true', the covariant Riemann
     tensor is computed directly from the frame field coefficients.
     Otherwise, the (3,1) Riemann tensor is computed first.

     For information on index ordering, see 'riemann'.

 -- Function: uriemann (<dis>)

     Computes the contravariant components of the Riemann curvature
     tensor as array elements 'uriem[i,j,k,l]'.  These are displayed if
     <dis> is 'true'.

 -- Function: rinvariant ()

     Forms the Kretchmann-invariant ('kinvariant') obtained by
     contracting the tensors

          lriem[i,j,k,l]*uriem[i,j,k,l].

     This object is not automatically simplified since it can be very
     large.

 -- Function: weyl (<dis>)

     Computes the Weyl conformal tensor.  If the argument <dis> is
     'true', the non-zero components 'weyl[i,j,k,l]' will be displayed
     to the user.  Otherwise, these components will simply be computed
     and stored.  If the switch 'ratweyl' is set to 'true', then the
     components will be rationally simplified; if 'ratfac' is 'true'
     then the results will be factored as well.

20.3.2.3 Taylor series expansion
................................

The 'ctensor' package has the ability to truncate results by assuming
that they are Taylor-series approximations.  This behavior is controlled
by the 'ctayswitch' variable; when set to true, 'ctensor' makes use
internally of the function 'ctaylor' when simplifying results.

The 'ctaylor' function is invoked by the following 'ctensor' functions:

         Function     Comments
         ---------------------------------
         christof()   For mcs only
         ricci()
         uricci()
         einstein()
         riemann()
         weyl()
         checkdiv()

 -- Function: ctaylor ()

     The 'ctaylor' function truncates its argument by converting it to a
     Taylor-series using 'taylor', and then calling 'ratdisrep'.  This
     has the combined effect of dropping terms higher order in the
     expansion variable 'ctayvar'.  The order of terms that should be
     dropped is defined by 'ctaypov'; the point around which the series
     expansion is carried out is specified in 'ctaypt'.

     As an example, consider a simple metric that is a perturbation of
     the Minkowski metric.  Without further restrictions, even a
     diagonal metric produces expressions for the Einstein tensor that
     are far too complex:

          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) ratfac:true;
          (%o2)                                true
          (%i3) derivabbrev:true;
          (%o3)                                true
          (%i4) ct_coords:[t,r,theta,phi];
          (%o4)                         [t, r, theta, phi]
          (%i5) lg:matrix([-1,0,0,0],[0,1,0,0],[0,0,r^2,0],
                          [0,0,0,r^2*sin(theta)^2]);
                                  [ - 1  0  0         0        ]
                                  [                            ]
                                  [  0   1  0         0        ]
                                  [                            ]
          (%o5)                   [          2                 ]
                                  [  0   0  r         0        ]
                                  [                            ]
                                  [              2    2        ]
                                  [  0   0  0   r  sin (theta) ]
          (%i6) h:matrix([h11,0,0,0],[0,h22,0,0],[0,0,h33,0],[0,0,0,h44]);
                                      [ h11   0    0    0  ]
                                      [                    ]
                                      [  0   h22   0    0  ]
          (%o6)                       [                    ]
                                      [  0    0   h33   0  ]
                                      [                    ]
                                      [  0    0    0   h44 ]
          (%i7) depends(l,r);
          (%o7)                               [l(r)]
          (%i8) lg:lg+l*h;
                [ h11 l - 1      0          0                 0            ]
                [                                                          ]
                [     0      h22 l + 1      0                 0            ]
                [                                                          ]
          (%o8) [                        2                                 ]
                [     0          0      r  + h33 l            0            ]
                [                                                          ]
                [                                    2    2                ]
                [     0          0          0       r  sin (theta) + h44 l ]
          (%i9) cmetric(false);
          (%o9)                                done
          (%i10) einstein(false);
          (%o10)                               done
          (%i11) ntermst(ein);
          [[1, 1], 62]
          [[1, 2], 0]
          [[1, 3], 0]
          [[1, 4], 0]
          [[2, 1], 0]
          [[2, 2], 24]
          [[2, 3], 0]
          [[2, 4], 0]
          [[3, 1], 0]
          [[3, 2], 0]
          [[3, 3], 46]
          [[3, 4], 0]
          [[4, 1], 0]
          [[4, 2], 0]
          [[4, 3], 0]
          [[4, 4], 46]
          (%o12)                               done

     However, if we recompute this example as an approximation that is
     linear in the variable 'l', we get much simpler expressions:

          (%i14) ctayswitch:true;
          (%o14)                               true
          (%i15) ctayvar:l;
          (%o15)                                 l
          (%i16) ctaypov:1;
          (%o16)                                 1
          (%i17) ctaypt:0;
          (%o17)                                 0
          (%i18) christof(false);
          (%o18)                               done
          (%i19) ricci(false);
          (%o19)                               done
          (%i20) einstein(false);
          (%o20)                               done
          (%i21) ntermst(ein);
          [[1, 1], 6]
          [[1, 2], 0]
          [[1, 3], 0]
          [[1, 4], 0]
          [[2, 1], 0]
          [[2, 2], 13]
          [[2, 3], 2]
          [[2, 4], 0]
          [[3, 1], 0]
          [[3, 2], 2]
          [[3, 3], 9]
          [[3, 4], 0]
          [[4, 1], 0]
          [[4, 2], 0]
          [[4, 3], 0]
          [[4, 4], 9]
          (%o21)                               done
          (%i22) ratsimp(ein[1,1]);
                                   2      2  4               2     2
          (%o22) - (((h11 h22 - h11 ) (l )  r  - 2 h33 l    r ) sin (theta)
                                        r               r r

                                      2               2      4    2
                        - 2 h44 l    r  - h33 h44 (l ) )/(4 r  sin (theta))
                                 r r                r

     This capability can be useful, for instance, when working in the
     weak field limit far from a gravitational source.

20.3.2.4 Frame fields
.....................

 -- Optionsvariable: cframe_flag
     Standardwert: 'false'

     When the variable 'cframe_flag' is set to true, the 'ctensor'
     package performs its calculations using a moving frame.

 -- Function: frame_bracket (<fr>, <fri>, <diagframe>)

     The frame bracket ('fb[]').

     Computes the frame bracket according to the following definition:

             c          c         c        d     e
          ifb   = ( ifri    - ifri    ) ifr   ifr
             ab         d,e       e,d      a     b

20.3.2.5 Algebraic classification
.................................

A new feature (as of November, 2004) of 'ctensor' is its ability to
compute the Petrov classification of a 4-dimensional spacetime metric.
For a demonstration of this capability, see the file
'share/tensor/petrov.dem'.

 -- Function: nptetrad ()

     Computes a Newman-Penrose null tetrad ('np') and its raised-index
     counterpart ('npi').  See 'petrov' for an example.

     The null tetrad is constructed on the assumption that a
     four-diemensional orthonormal frame metric with metric signature
     (-,+,+,+) is being used.  The components of the null tetrad are
     related to the inverse frame matrix as follows:

          np  = (fri  + fri ) / sqrt(2)
            1       1      2

          np  = (fri  - fri ) / sqrt(2)
            2       1      2

          np  = (fri  + %i fri ) / sqrt(2)
            3       3         4

          np  = (fri  - %i fri ) / sqrt(2)
            4       3         4

 -- Function: psi (<dis>)

     Computes the five Newman-Penrose coefficients 'psi[0]'...'psi[4]'.
     If 'psi' is set to 'true', the coefficients are displayed.  See
     'petrov' for an example.

     These coefficients are computed from the Weyl-tensor in a
     coordinate base.  If a frame base is used, the Weyl-tensor is first
     converted to a coordinate base, which can be a computationally
     expensive procedure.  For this reason, in some cases it may be more
     advantageous to use a coordinate base in the first place before the
     Weyl tensor is computed.  Note however, that constructing a
     Newman-Penrose null tetrad requires a frame base.  Therefore, a
     meaningful computation sequence may begin with a frame base, which
     is then used to compute 'lg' (computed automatically by 'cmetric'
     and then 'ug'.  At this point, you can switch back to a coordinate
     base by setting 'cframe_flag' to false before beginning to compute
     the Christoffel symbols.  Changing to a frame base at a later stage
     could yield inconsistent results, as you may end up with a mixed
     bag of tensors, some computed in a frame base, some in a coordinate
     base, with no means to distinguish between the two.

 -- Function: petrov ()

     Computes the Petrov classification of the metric characterized by
     'psi[0]' ... 'psi[4]'.

     For example, the following demonstrates how to obtain the
     Petrov-classification of the Kerr metric:

          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) (cframe_flag:true,gcd:spmod,ctrgsimp:true,ratfac:true);
          (%o2)                                true
          (%i3) ct_coordsys(exteriorschwarzschild,all);
          (%o3)                                done
          (%i4) ug:invert(lg)$
          (%i5) weyl(false);
          (%o5)                                done
          (%i6) nptetrad(true);
          (%t6) np =

          [ sqrt(r - 2 m)           sqrt(r)                                 ]
          [---------------   ---------------------    0            0        ]
          [sqrt(2) sqrt(r)   sqrt(2) sqrt(r - 2 m)                          ]
          [                                                                 ]
          [ sqrt(r - 2 m)            sqrt(r)                                ]
          [---------------  - ---------------------   0            0        ]
          [sqrt(2) sqrt(r)    sqrt(2) sqrt(r - 2 m)                         ]
          [                                                                 ]
          [                                          r      %i r sin(theta) ]
          [       0                    0          -------   --------------- ]
          [                                       sqrt(2)       sqrt(2)     ]
          [                                                                 ]
          [                                          r       %i r sin(theta)]
          [       0                    0          -------  - ---------------]
          [                                       sqrt(2)        sqrt(2)    ]

                                       sqrt(r)         sqrt(r - 2 m)
          (%t7) npi = matrix([- ---------------------,---------------, 0, 0],
                                sqrt(2) sqrt(r - 2 m) sqrt(2) sqrt(r)

                    sqrt(r)            sqrt(r - 2 m)
          [- ---------------------, - ---------------, 0, 0],
             sqrt(2) sqrt(r - 2 m)    sqrt(2) sqrt(r)

                     1               %i
          [0, 0, ---------, --------------------],
                 sqrt(2) r  sqrt(2) r sin(theta)

                     1                 %i
          [0, 0, ---------, - --------------------])
                 sqrt(2) r    sqrt(2) r sin(theta)

          (%o7)                                done
          (%i7) psi(true);
          (%t8)                              psi  = 0
                                                0

          (%t9)                              psi  = 0
                                                1

                                                    m
          (%t10)                             psi  = --
                                                2    3
                                                    r

          (%t11)                             psi  = 0
                                                3

          (%t12)                             psi  = 0
                                                4
          (%o12)                               done
          (%i12) petrov();
          (%o12)                                 D

     The Petrov classification function is based on the algorithm
     published in "Classifying geometries in general relativity: III
     Classification in practice" by Pollney, Skea, and d'Inverno, Class.
     Quant.  Grav.  17 2885-2902 (2000).  Except for some simple test
     cases, the implementation is untested as of December 19, 2004, and
     is likely to contain errors.

20.3.2.6 Torsion and nonmetricity
.................................

'ctensor' has the ability to compute and include torsion and
nonmetricity coefficients in the connection coefficients.

The torsion coefficients are calculated from a user-supplied tensor
'tr', which should be a rank (2,1) tensor.  From this, the torsion
coefficients 'kt' are computed according to the following formulae:

                   m          m      m
            - g  tr   - g   tr   - tr   g
               im  kj    jm   ki     ij  km
     kt   = -------------------------------
       ijk                 2


       k     km
     kt   = g   kt
       ij         ijm

Note that only the mixed-index tensor is calculated and stored in the
array 'kt'.

The nonmetricity coefficients are calculated from the user-supplied
nonmetricity vector 'nm'.  From this, the nonmetricity coefficients
'nmc' are computed as follows:

                  k    k        km
            -nm  D  - D  nm  + g   nm  g
        k      i  j    i   j         m  ij
     nmc  = ------------------------------
        ij                2

where D stands for the Kronecker-delta.

When 'ctorsion_flag' is set to 'true', the values of 'kt' are
substracted from the mixed-indexed connection coefficients computed by
'christof' and stored in 'mcs'.  Similarly, if 'cnonmet_flag' is set to
'true', the values of 'nmc' are substracted from the mixed-indexed
connection coefficients.

If necessary, 'christof' calls the functions 'contortion' and
'nonmetricity' in order to compute 'kt' and 'nm'.

 -- Function: contortion (<tr>)

     Computes the (2,1) contortion coefficients from the torsion tensor
     <tr>.

 -- Function: nonmetricity (<nm>)

     Computes the (2,1) nonmetricity coefficients from the nonmetricity
     vector <nm>.

20.3.2.7 Miscellaneous features
...............................

 -- Function: ctransform (<M>)

     A function in the 'ctensor' (component tensor) package which will
     perform a coordinate transformation upon an arbitrary square
     symmetric matrix <M>.  The user must input the functions which
     define the transformation.  (Formerly called 'transform'.)

 -- Function: findde (<A>, <n>)

     returns a list of the unique differential equations (expressions)
     corresponding to the elements of the <n> dimensional square array
     <A>.  Presently, <n> may be 2 or 3.  'deindex' is a global list
     containing the indices of <A> corresponding to these unique
     differential equations.  For the Einstein tensor ('ein'), which is
     a two dimensional array, if computed for the metric in the example
     below, 'findde' gives the following independent differential
     equations:

          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) derivabbrev:true;
          (%o2)                                true
          (%i3) dim:4;
          (%o3)                                  4
          (%i4) lg:matrix([a, 0, 0, 0], [ 0, x^2, 0, 0],
                                        [0, 0, x^2*sin(y)^2, 0], [0,0,0,-d]);
                                    [ a  0       0        0  ]
                                    [                        ]
                                    [     2                  ]
                                    [ 0  x       0        0  ]
          (%o4)                     [                        ]
                                    [         2    2         ]
                                    [ 0  0   x  sin (y)   0  ]
                                    [                        ]
                                    [ 0  0       0       - d ]
          (%i5) depends([a,d],x);
          (%o5)                            [a(x), d(x)]
          (%i6) ct_coords:[x,y,z,t];
          (%o6)                            [x, y, z, t]
          (%i7) cmetric();
          (%o7)                                done
          (%i8) einstein(false);
          (%o8)                                done
          (%i9) findde(ein,2);
                                                      2
          (%o9) [d  x - a d + d, 2 a d d    x - a (d )  x - a  d d  x
                  x                     x x         x        x    x

                                                        2          2
                                    + 2 a d d   - 2 a  d , a  x + a  - a]
                                             x       x      x
          (%i10) deindex;
          (%o10)                     [[1, 1], [2, 2], [4, 4]]

 -- Function: cograd ()

     Computes the covariant gradient of a scalar function allowing the
     user to choose the corresponding vector name as the example under
     'contragrad' illustrates.

 -- Function: contragrad ()

     Computes the contravariant gradient of a scalar function allowing
     the user to choose the corresponding vector name as the example
     below for the Schwarzschild metric illustrates:

          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) derivabbrev:true;
          (%o2)                                true
          (%i3) ct_coordsys(exteriorschwarzschild,all);
          (%o3)                                done
          (%i4) depends(f,r);
          (%o4)                               [f(r)]
          (%i5) cograd(f,g1);
          (%o5)                                done
          (%i6) listarray(g1);
          (%o6)                            [0, f , 0, 0]
                                                r
          (%i7) contragrad(f,g2);
          (%o7)                                done
          (%i8) listarray(g2);
                                         f  r - 2 f  m
                                          r        r
          (%o8)                      [0, -------------, 0, 0]
                                               r

 -- Function: dscalar ()

     computes the tensor d'Alembertian of the scalar function once
     dependencies have been declared upon the function.  For example:

          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) derivabbrev:true;
          (%o2)                                true
          (%i3) ct_coordsys(exteriorschwarzschild,all);
          (%o3)                                done
          (%i4) depends(p,r);
          (%o4)                               [p(r)]
          (%i5) factor(dscalar(p));
                                    2
                              p    r  - 2 m p    r + 2 p  r - 2 m p
                               r r           r r        r          r
          (%o5)               --------------------------------------
                                                 2
                                                r

 -- Function: checkdiv ()

     computes the covariant divergence of the mixed second rank tensor
     (whose first index must be covariant) by printing the corresponding
     n components of the vector field (the divergence) where n = 'dim'.
     If the argument to the function is 'g' then the divergence of the
     Einstein tensor will be formed and must be zero.  In addition, the
     divergence (vector) is given the array name 'div'.

 -- Function: cgeodesic (<dis>)

     A function in the 'ctensor' (component tensor) package.
     'cgeodesic' computes the geodesic equations of motion for a given
     metric.  They are stored in the array 'geod[i]'.  If the argument
     <dis> is 'true' then these equations are displayed.

 -- Function: bdvac (<f>)

     generates the covariant components of the vacuum field equations of
     the Brans- Dicke gravitational theory.  The scalar field is
     specified by the argument <f>, which should be a (quoted) function
     name with functional dependencies, e.g., ''p(x)'.

     The components of the second rank covariant field tensor are
     represented by the array 'bd'.

 -- Function: invariant1 ()

     generates the mixed Euler- Lagrange tensor (field equations) for
     the invariant density of R^2.  The field equations are the
     components of an array named 'inv1'.

 -- Function: invariant2 ()

     *** NOT YET IMPLEMENTED ***

     generates the mixed Euler- Lagrange tensor (field equations) for
     the invariant density of 'ric[i,j]*uriem[i,j]'.  The field
     equations are the components of an array named 'inv2'.

 -- Function: bimetric ()

     *** NOT YET IMPLEMENTED ***

     generates the field equations of Rosen's bimetric theory.  The
     field equations are the components of an array named 'rosen'.

20.3.2.8 Utility functions
..........................

 -- Function: diagmatrixp (<M>)

     Returns 'true' if <M> is a diagonal matrix or (2D) array.

 -- Function: symmetricp (<M>)

     Returns 'true' if <M> is a symmetric matrix or (2D) array.

 -- Function: ntermst (<f>)

     gives the user a quick picture of the "size" of the doubly
     subscripted tensor (array) <f>.  It prints two element lists where
     the second element corresponds to NTERMS of the components
     specified by the first elements.  In this way, it is possible to
     quickly find the non-zero expressions and attempt simplification.

 -- Function: cdisplay (<ten>)

     displays all the elements of the tensor <ten>, as represented by a
     multidimensional array.  Tensors of rank 0 and 1, as well as other
     types of variables, are displayed as with 'ldisplay'.  Tensors of
     rank 2 are displayed as 2-dimensional matrices, while tensors of
     higher rank are displayed as a list of 2-dimensional matrices.  For
     instance, the Riemann-tensor of the Schwarzschild metric can be
     viewed as:

          (%i1) load(ctensor);
          (%o1)       /share/tensor/ctensor.mac
          (%i2) ratfac:true;
          (%o2)                                true
          (%i3) ct_coordsys(exteriorschwarzschild,all);
          (%o3)                                done
          (%i4) riemann(false);
          (%o4)                                done
          (%i5) cdisplay(riem);
                    [ 0               0                   0           0     ]
                    [                                                       ]
                    [                              2                        ]
                    [      3 m (r - 2 m)   m    2 m                         ]
                    [ 0  - ------------- + -- - ----      0           0     ]
                    [            4          3     4                         ]
                    [           r          r     r                          ]
                    [                                                       ]
          riem    = [                                m (r - 2 m)            ]
              1, 1  [ 0               0              -----------      0     ]
                    [                                     4                 ]
                    [                                    r                  ]
                    [                                                       ]
                    [                                           m (r - 2 m) ]
                    [ 0               0                   0     ----------- ]
                    [                                                4      ]
                    [                                               r       ]

                                          [    2 m (r - 2 m)       ]
                                          [ 0  -------------  0  0 ]
                                          [          4             ]
                                          [         r              ]
                               riem     = [                        ]
                                   1, 2   [ 0        0        0  0 ]
                                          [                        ]
                                          [ 0        0        0  0 ]
                                          [                        ]
                                          [ 0        0        0  0 ]

                                          [         m (r - 2 m)    ]
                                          [ 0  0  - -----------  0 ]
                                          [              4         ]
                                          [             r          ]
                               riem     = [                        ]
                                   1, 3   [ 0  0        0        0 ]
                                          [                        ]
                                          [ 0  0        0        0 ]
                                          [                        ]
                                          [ 0  0        0        0 ]

                                          [            m (r - 2 m) ]
                                          [ 0  0  0  - ----------- ]
                                          [                 4      ]
                                          [                r       ]
                               riem     = [                        ]
                                   1, 4   [ 0  0  0        0       ]
                                          [                        ]
                                          [ 0  0  0        0       ]
                                          [                        ]
                                          [ 0  0  0        0       ]

                                         [       0         0  0  0 ]
                                         [                         ]
                                         [       2 m               ]
                                         [ - ------------  0  0  0 ]
                              riem     = [    2                    ]
                                  2, 1   [   r  (r - 2 m)          ]
                                         [                         ]
                                         [       0         0  0  0 ]
                                         [                         ]
                                         [       0         0  0  0 ]

                       [     2 m                                         ]
                       [ ------------  0        0               0        ]
                       [  2                                              ]
                       [ r  (r - 2 m)                                    ]
                       [                                                 ]
                       [      0        0        0               0        ]
                       [                                                 ]
            riem     = [                         m                       ]
                2, 2   [      0        0  - ------------        0        ]
                       [                     2                           ]
                       [                    r  (r - 2 m)                 ]
                       [                                                 ]
                       [                                         m       ]
                       [      0        0        0         - ------------ ]
                       [                                     2           ]
                       [                                    r  (r - 2 m) ]

                                          [ 0  0       0        0 ]
                                          [                       ]
                                          [            m          ]
                                          [ 0  0  ------------  0 ]
                               riem     = [        2              ]
                                   2, 3   [       r  (r - 2 m)    ]
                                          [                       ]
                                          [ 0  0       0        0 ]
                                          [                       ]
                                          [ 0  0       0        0 ]

                                          [ 0  0  0       0       ]
                                          [                       ]
                                          [               m       ]
                                          [ 0  0  0  ------------ ]
                               riem     = [           2           ]
                                   2, 4   [          r  (r - 2 m) ]
                                          [                       ]
                                          [ 0  0  0       0       ]
                                          [                       ]
                                          [ 0  0  0       0       ]

                                                [ 0  0  0  0 ]
                                                [            ]
                                                [ 0  0  0  0 ]
                                                [            ]
                                     riem     = [ m          ]
                                         3, 1   [ -  0  0  0 ]
                                                [ r          ]
                                                [            ]
                                                [ 0  0  0  0 ]

                                                [ 0  0  0  0 ]
                                                [            ]
                                                [ 0  0  0  0 ]
                                                [            ]
                                     riem     = [    m       ]
                                         3, 2   [ 0  -  0  0 ]
                                                [    r       ]
                                                [            ]
                                                [ 0  0  0  0 ]

                                         [   m                      ]
                                         [ - -   0   0       0      ]
                                         [   r                      ]
                                         [                          ]
                                         [        m                 ]
                                         [  0   - -  0       0      ]
                              riem     = [        r                 ]
                                  3, 3   [                          ]
                                         [  0    0   0       0      ]
                                         [                          ]
                                         [              2 m - r     ]
                                         [  0    0   0  ------- + 1 ]
                                         [                 r        ]

                                              [ 0  0  0    0   ]
                                              [                ]
                                              [ 0  0  0    0   ]
                                              [                ]
                                   riem     = [            2 m ]
                                       3, 4   [ 0  0  0  - --- ]
                                              [             r  ]
                                              [                ]
                                              [ 0  0  0    0   ]

                                          [       0        0  0  0 ]
                                          [                        ]
                                          [       0        0  0  0 ]
                                          [                        ]
                               riem     = [       0        0  0  0 ]
                                   4, 1   [                        ]
                                          [      2                 ]
                                          [ m sin (theta)          ]
                                          [ -------------  0  0  0 ]
                                          [       r                ]

                                          [ 0        0        0  0 ]
                                          [                        ]
                                          [ 0        0        0  0 ]
                                          [                        ]
                               riem     = [ 0        0        0  0 ]
                                   4, 2   [                        ]
                                          [         2              ]
                                          [    m sin (theta)       ]
                                          [ 0  -------------  0  0 ]
                                          [          r             ]

                                        [ 0  0          0          0 ]
                                        [                            ]
                                        [ 0  0          0          0 ]
                                        [                            ]
                             riem     = [ 0  0          0          0 ]
                                 4, 3   [                            ]
                                        [                2           ]
                                        [         2 m sin (theta)    ]
                                        [ 0  0  - ---------------  0 ]
                                        [                r           ]

                     [        2                                             ]
                     [   m sin (theta)                                      ]
                     [ - -------------         0                0         0 ]
                     [         r                                            ]
                     [                                                      ]
                     [                         2                            ]
                     [                    m sin (theta)                     ]
          riem     = [        0         - -------------         0         0 ]
              4, 4   [                          r                           ]
                     [                                                      ]
                     [                                          2           ]
                     [                                   2 m sin (theta)    ]
                     [        0                0         ---------------  0 ]
                     [                                          r           ]
                     [                                                      ]
                     [        0                0                0         0 ]

          (%o5)                                done

 -- Function: deleten (<L>, <n>)

     Returns a new list consisting of <L> with the <n>'th element
     deleted.

20.3.2.9 Variables used by 'ctensor'
....................................

 -- Option variable: dim
     Default value: 4

     An option in the 'ctensor' (component tensor) package.  'dim' is
     the dimension of the manifold with the default 4.  The command
     'dim: n' will reset the dimension to any other value 'n'.

 -- Option variable: diagmetric
     Default value: 'false'

     An option in the 'ctensor' (component tensor) package.  If
     'diagmetric' is 'true' special routines compute all geometrical
     objects (which contain the metric tensor explicitly) by taking into
     consideration the diagonality of the metric.  Reduced run times
     will, of course, result.  Note: this option is set automatically by
     'csetup' if a diagonal metric is specified.

 -- Option variable: ctrgsimp

     Causes trigonometric simplifications to be used when tensors are
     computed.  Presently, 'ctrgsimp' affects only computations
     involving a moving frame.

 -- Option variable: cframe_flag

     Causes computations to be performed relative to a moving frame as
     opposed to a holonomic metric.  The frame is defined by the inverse
     frame array 'fri' and the frame metric 'lfg'.  For computations
     using a Cartesian frame, 'lfg' should be the unit matrix of the
     appropriate dimension; for computations in a Lorentz frame, 'lfg'
     should have the appropriate signature.

 -- Option variable: ctorsion_flag

     Causes the contortion tensor to be included in the computation of
     the connection coefficients.  The contortion tensor itself is
     computed by 'contortion' from the user-supplied tensor 'tr'.

 -- Option variable: cnonmet_flag

     Causes the nonmetricity coefficients to be included in the
     computation of the connection coefficients.  The nonmetricity
     coefficients are computed from the user-supplied nonmetricity
     vector 'nm' by the function 'nonmetricity'.

 -- Option variable: ctayswitch

     If set to 'true', causes some 'ctensor' computations to be carried
     out using Taylor-series expansions.  Presently, 'christof',
     'ricci', 'uricci', 'einstein', and 'weyl' take into account this
     setting.

 -- Option variable: ctayvar

     Variable used for Taylor-series expansion if 'ctayswitch' is set to
     'true'.

 -- Option variable: ctaypov

     Maximum power used in Taylor-series expansion when 'ctayswitch' is
     set to 'true'.

 -- Option variable: ctaypt

     Point around which Taylor-series expansion is carried out when
     'ctayswitch' is set to 'true'.

 -- System variable: gdet

     The determinant of the metric tensor 'lg'.  Computed by 'cmetric'
     when 'cframe_flag' is set to 'false'.

 -- Option variable: ratchristof

     Causes rational simplification to be applied by 'christof'.

 -- Option variable: rateinstein
     Default value: 'true'

     If 'true' rational simplification will be performed on the non-zero
     components of Einstein tensors; if 'ratfac' is 'true' then the
     components will also be factored.

 -- Option variable: ratriemann
     Default value: 'true'

     One of the switches which controls simplification of Riemann
     tensors; if 'true', then rational simplification will be done; if
     'ratfac' is 'true' then each of the components will also be
     factored.

 -- Option variable: ratweyl
     Default value: 'true'

     If 'true', this switch causes the 'weyl' function to apply rational
     simplification to the values of the Weyl tensor.  If 'ratfac' is
     'true', then the components will also be factored.

 -- Variable: lfg

     The covariant frame metric.  By default, it is initialized to the
     4-dimensional Lorentz frame with signature (+,+,+,-).  Used when
     'cframe_flag' is 'true'.

 -- Variable: ufg

     The inverse frame metric.  Computed from 'lfg' when 'cmetric' is
     called while 'cframe_flag' is set to 'true'.

 -- Variable: riem

     The (3,1) Riemann tensor.  Computed when the function 'riemann' is
     invoked.  For information about index ordering, see the description
     of 'riemann'.

     If 'cframe_flag' is 'true', 'riem' is computed from the covariant
     Riemann-tensor 'lriem'.

 -- Variable: lriem

     The covariant Riemann tensor.  Computed by 'lriemann'.

 -- Variable: uriem

     The contravariant Riemann tensor.  Computed by 'uriemann'.

 -- Variable: ric

     The mixed Ricci-tensor.  Computed by 'ricci'.

 -- Variable: uric

     The contravariant Ricci-tensor.  Computed by 'uricci'.

 -- Variable: lg

     The metric tensor.  This tensor must be specified (as a 'dim' by
     'dim' matrix) before other computations can be performed.

 -- Variable: ug

     The inverse of the metric tensor.  Computed by 'cmetric'.

 -- Variable: weyl

     The Weyl tensor.  Computed by 'weyl'.

 -- Variable: fb

     Frame bracket coefficients, as computed by 'frame_bracket'.

 -- Variable: kinvariant

     The Kretchmann invariant.  Computed by 'rinvariant'.

 -- Variable: np

     A Newman-Penrose null tetrad.  Computed by 'nptetrad'.

 -- Variable: npi

     The raised-index Newman-Penrose null tetrad.  Computed by
     'nptetrad'.  Defined as 'ug.np'.  The product 'np.transpose(npi)'
     is constant:

          (%i39) trigsimp(np.transpose(npi));
                                        [  0   - 1  0  0 ]
                                        [                ]
                                        [ - 1   0   0  0 ]
          (%o39)                        [                ]
                                        [  0    0   0  1 ]
                                        [                ]
                                        [  0    0   1  0 ]

 -- Variable: tr

     User-supplied rank-3 tensor representing torsion.  Used by
     'contortion'.

 -- Variable: kt

     The contortion tensor, computed from 'tr' by 'contortion'.

 -- Variable: nm

     User-supplied nonmetricity vector.  Used by 'nonmetricity'.

 -- Variable: nmc

     The nonmetricity coefficients, computed from 'nm' by
     'nonmetricity'.

 -- System variable: tensorkill

     Variable indicating if the tensor package has been initialized.
     Set and used by 'csetup', reset by 'init_ctensor'.

 -- Option variable: ct_coords
     Default value: '[]'

     An option in the 'ctensor' (component tensor) package.  'ct_coords'
     contains a list of coordinates.  While normally defined when the
     function 'csetup' is called, one may redefine the coordinates with
     the assignment 'ct_coords: [j1, j2, ..., jn]' where the j's are the
     new coordinate names.  See also 'csetup'.

20.3.2.10 Reserved names
........................

The following names are used internally by the 'ctensor' package and
should not be redefined:

       Name         Description
       ---------------------------------------------------------------------
       _lg()        Evaluates to lfg if frame metric used, lg otherwise
       _ug()        Evaluates to ufg if frame metric used, ug otherwise
       cleanup()    Removes items drom the deindex list
       contract4()  Used by psi()
       filemet()    Used by csetup() when reading the metric from a file
       findde1()    Used by findde()
       findde2()    Used by findde()
       findde3()    Used by findde()
       kdelt()      Kronecker-delta (not generalized)
       newmet()     Used by csetup() for setting up a metric interactively
       setflags()   Used by init_ctensor()
       readvalue()
       resimp()
       sermet()     Used by csetup() for entering a metric as Taylor-series
       txyzsum()
       tmetric()    Frame metric, used by cmetric() when cframe_flag:true
       triemann()   Riemann-tensor in frame base, used when cframe_flag:true
       tricci()     Ricci-tensor in frame base, used when cframe_flag:true
       trrc()       Ricci rotation coefficients, used by christof()
       yesp()

20.3.2.11 Changes
.................

In November, 2004, the 'ctensor' package was extensively rewritten.
Many functions and variables have been renamed in order to make the
package compatible with the commercial version of Macsyma.

       New Name     Old Name        Description
       ---------------------------------------------------------------------
       ctaylor()    DLGTAYLOR()     Taylor-series expansion of an expression
       lgeod[]      EM              Geodesic equations
       ein[]        G[]             Mixed Einstein-tensor
       ric[]        LR[]            Mixed Ricci-tensor
       ricci()      LRICCICOM()     Compute the mixed Ricci-tensor
       ctaypov      MINP            Maximum power in Taylor-series expansion
       cgeodesic()  MOTION          Compute geodesic equations
       ct_coords    OMEGA           Metric coordinates
       ctayvar      PARAM           Taylor-series expansion variable
       lriem[]      R[]             Covariant Riemann-tensor
       uriemann()   RAISERIEMANN()  Compute the contravariant Riemann-tensor
       ratriemann   RATRIEMAN       Rational simplif. of the Riemann-tensor
       uric[]       RICCI[]         Contravariant Ricci-tensor
       uricci()     RICCICOM()      Compute the contravariant Ricci-tensor
       cmetric()    SETMETRIC()     Set up the metric
       ctaypt       TAYPT           Point for Taylor-series expansion
       ctayswitch   TAYSWITCH       Taylor-series setting switch
       csetup()     TSETUP()        Start interactive setup session
       ctransform() TTRANSFORM()    Interactive coordinate transformation
       uriem[]      UR[]            Contravariant Riemann-tensor
       weyl[]       W[]             (3,1) Weyl-tensor


File: maxima.info,  Node: Paket atensor,  Prev: Paket ctensor,  Up: Tensoren

20.4 Paket ATENSOR
==================

* Menu:

* Einführung in atensor::
* Funktionen und Variablen für atensor::


File: maxima.info,  Node: Einführung in atensor,  Next: Funktionen und Variablen für atensor,  Prev: Paket atensor,  Up: Paket atensor

20.4.1 Einführung in ATENSOR
----------------------------

Das Paket 'atensor' erlaubt das algebraische Rechnen mit Tensoren.  Mit
dem Kommando 'load(atensor)' wird das Paket geladen.  Um das Paket zu
initialisieren, wird die Funktion 'init_atensor' ausgeführt.

Im wesentlichen enthält das Paket 'atensor' Regeln für die Vereinfachung
von Ausdrücken mit dem 'dot-Operator' Operator '"."'.  'atensor' kennt
verschiedene Algebren.  Mit der Funktion 'init_atensor' werden die
Regeln einer Algebra initialisiert.

Um die Möglichkeiten des Paketes 'atensor' zu zeigen, wird im Folgenden
die Algebra der Quaternionen als eine Clifford-Algebra Cl(0,2) mit zwei
Basisvektoren definiert.  Die drei imaginären Einheiten 'i', 'j' und 'k'
werden durch die zwei Vektoren 'v[1]' und 'v[2]' sowie das Produkt 'v[1]
. v[2]' dargestellt:

         i = v     j = v     k = v  . v
              1         2         1    2

Das Paket 'atensor' hat eine vordefinierte Algebra der Quaternionen.
Hier wird die Algebra der Quaterinonen als Clifford-Algebra Cl(0,2)
definiert und die Multiplikationstabelle der Basisvektoren konstruiert.

     (%i1) load(atensor)$

     (%i2) init_atensor(clifford,0,0,2);
     (%o2)                         done
     (%i3) atensimp(v[1].v[1]);
     (%o3)                          - 1
     (%i4) atensimp((v[1].v[2]).(v[1].v[2]));
     (%o4)                          - 1
     (%i5) q:zeromatrix(4,4);
                              [ 0  0  0  0 ]
                              [            ]
                              [ 0  0  0  0 ]
     (%o5)                    [            ]
                              [ 0  0  0  0 ]
                              [            ]
                              [ 0  0  0  0 ]
     (%i6) q[1,1]:1;
     (%o6)                           1
     (%i7) for i thru adim do q[1,i+1]:q[i+1,1]:v[i];
     (%o7)                         done
     (%i8) q[1,4]:q[4,1]:v[1].v[2];
     (%o8)                        v  . v
                                   1    2
     (%i9) for i from 2 thru 4 do
               for j from 2 thru 4 do
                   q[i,j]:atensimp(q[i,1].q[1,j]);
     (%o9)                         done
     (%i10) q;
                 [    1        v         v      v  . v  ]
                 [              1         2      1    2 ]
                 [                                      ]
                 [   v         - 1     v  . v    - v    ]
                 [    1                 1    2      2   ]
     (%o10)      [                                      ]
                 [   v      - v  . v     - 1      v     ]
                 [    2        1    2              1    ]
                 [                                      ]
                 [ v  . v      v        - v       - 1   ]
                 [  1    2      2          1            ]

Indizierte Symbole mit dem Namen, der in der Optionsvariablen 'asymbol'
abgelegt ist, werden von 'atensor' als Basisvektoren erkannt.  Dabei
läuft der Index von '1' bis 'adim'.  Für indizierte Symbole werden die
Bilinearformen 'sf', 'af' und 'av' ausgewertet.  Die Auswertung ersetzt
die Bilinearform 'fun(v[i].v[j])', durch das Matrixelement 'aform[i,j]',
wobei 'v' einen Basisvektor bezeichnet und 'fun' einer der
Bilinearformen 'sf' oder 'af' ist.  Ist 'fun' die Bilinearform 'av',
dann wird 'v[aform[i,j]]' für 'av(v[i],v[j])' substituiert.  Siehe auch
die Optionsvariable 'aform'.

Die Bilinearformen 'sf', 'af' und 'av' können vom Nutzer neu definiert
werden, um eine gewünschte Algebra zu definieren.

Wird das Paket 'atensor' geladen, werden die folgenden Schalter auf die
angegebenen Werte gesetzt:

     dotscrules  : true
     dotdistrib  : true
     dotexptsimp : false

Wird das symbolische Rechnen in einer nicht-assoziativen Algebra
gewünscht, kann auch noch der Schalter 'dotassoc' auf den Wert 'false'
gesetzt werden.  In diesem Fall kann jedoch die Funktion 'atensimp'
nicht immer eine gewünschte Vereinfachung erzielen.


File: maxima.info,  Node: Funktionen und Variablen für atensor,  Prev: Einführung in atensor,  Up: Paket atensor

20.4.2 Funktionen und Variablen für ATENSOR
-------------------------------------------

 -- Funktion: init_atensor (<alg_type>, <opt_dims>)
 -- Funktion: init_atensor (<alg_type>)

     Initialisiert das Paket 'atensor' mit der angegebenen Algebra
     <alg_type>.  Das Argument <alg_type> kann einen der folgenden Werte
     haben:

     'universal'
          Eine allgemeine Algebra, für die keine Vertauschungsregeln
          definiert sind.

     'grassmann'
          Eine Graßmann-Algebra, für die die Vertauschungsregel 'u.v +
          v.u = 0' definiert ist.

     'clifford'
          Eine Clifford-Algebra, die durch die Vertauschungsregel 'u.v +
          v.u = -2*sf(u,v)' definiert ist.  Die Bilinearform 'sf' ist
          eine symmetrische Funktion, die einen skalaren Wert als
          Ergebnis hat.  Das Argument <opt_dims> kann bis zu drei
          positive ganze Zahlen sein, die die positiven, entarteten und
          negativen Dimensionen der Algebra bezeichnen.  Die Dimension
          'adim' und die Matrix 'aform' werden entsprechend der
          angegebenen Argumente <opt_dims> initialisiert.  Sind keine
          Argumente <opt_dims> vorhanden, wird die Dimension 'adim' zu
          Null initialisiert und keine Matrix 'aform' definiert.

     'symmetric'
          Eine symmetrische Algebra, die durch die Vertauschungsregel
          'u.v - v.u = 0' definiert ist.

     'symplectic'
          Eine symplektische Algebra, die durch die Vertauschungsregel
          'u.v - v.u = 2*af(u,v)' definiert ist.  Die Bilinearform 'af'
          ist eine antisymmetrische Funktion, die einen skalaren Wert
          als Ergebnis hat.  Das Argument <opt_dims> kann bis zu zwei
          positive ganze Zahlen enthalten, die die nicht-degenerierten
          und degenerierten Dimensionen der Algebra bezeichnen.  Die
          Dimension 'adim' und die Matrix 'aform' werden entsprechend
          der angegebenen Argumente <opt_dims> initialisiert.  Sind
          keine Argumente <opt_dims> vorhanden, wird die Dimension
          'adim' zu Null initialisiert und keine Matrix 'aform'
          definiert.

     'lie_envelop'
          Eine einhüllende Lie-Algebra, die durch die Vertauschungsregel
          'u.v - v.u = 2*av(u,v)' definiert ist, wobei die Bilinearform
          'av' eine antisymmetrische Funktion ist.  Das Argument
          <opt_dims> kann eine positive ganze Zahl sein, welche die
          Dimension der Lie-Algebra angibt.  Die Dimension 'adim' und
          die Matrix 'aform' werden entsprechend des Argumentes
          <opt_dims> initialisiert.  Ist kein Argument <opt_dims>
          vorhanden, wird die Dimension 'adim' zu Null initialisiert und
          keine Matrix 'aform' definiert.

     Die Funktion 'init_atensor' kennt weiterhin einige vordefinierte
     Algebren:

     'complex'
          Die Algebra der komplexen Zahlen, die als eine
          Clifford-Algebra Cl(0,1) definiert wird.  Das Kommando
          'init_atensor(complex)' ist äquivalent zum Kommando
          'init_atensor(clifford, 0, 0, 1)'.

     'quaternion'
          Die Algebra der Quaternionen, die als eine Clifford-Algebra
          vom Typ Cl(0,2) definiert wird.  Das Kommando
          'init_atensor(quaternion)' ist äquivalent zum Kommando
          'init_atensor(clifford, 0, 0, 2)'.

     'pauli'
          Die Algebra der Pauli-Matrizen, die als eine Clifford-Algebra
          Cl(3,0) definiert wird.  Das Kommando 'init_atensor(pauli)'
          ist äquivalent zum Kommando 'init_atensor(clifford, 3)'.

     'dirac'
          Die Algebra der Dirac-Matrizen, die als eine Clifford-Algebra
          Cl(3,0,1) definiert wird.  Das Kommando 'init_atensor(dirac)'
          ist äquivalent zum Kommando 'init_atensor(clifford, 3, 0, 1)'.

 -- Funktion: atensimp (<expr>)

     Vereinfacht einen Ausdruck <expr> entsprechend der Regeln für die
     Algebra, die mit der Funktion 'init_atensor' festgelegt ist.  Die
     Regeln werden rekursiv auf den Ausdruck angewendet.  Dabei werden
     auch Bilinearformen 'sf', 'af' und 'av' ausgewertet.

     Beispiele:

     Die folgenden Beispiele zeigen das Rechnen mit der Algebra der
     Quaternionen.

          (%i1) load(atensor)$

          (%i2) init_atensor(quaternion);
          (%o2)                         done
          (%i3) atensimp(v[1].v[1]);
          (%o3)                          - 1
          (%i4) atensimp(v[2].v[2]);
          (%o4)                          - 1
          (%i5) atensimp((v[1].v[2]) . (v[1].v[2]));
          (%o5)                          - 1
          (%i6) expand((2*v[1]+3*v[2])^^2);
          (%o6) 9 (v  . v ) + 6 (v  . v ) + 6 (v  . v ) + 4 (v  . v )
                    2    2        2    1        1    2        1    1
          (%i7) atensimp(%);
          (%o7)                         - 13

 -- Optionsvariable: alg_type
     Standardwert: 'universal'

     Der Typ der Algebra, die bei der Vereinfachung von Ausdrücken mit
     der Funktion 'atensimp' angewendet wird.  Die Algebra wird von der
     Funktion 'init_atensor' initialisiert.  Mögliche Algebren sind
     'universal', 'grassmann', 'clifford', 'symmetric', 'symplectic' und
     'lie_envelop'.  Siehe für eine ausführliche Erläuterung der
     Algebren die Funktion 'init_atensor'.

 -- Optionsvariable: adim
     Standardwert: '0'

     Die Dimension der Algebra, die bei der Vereinfachung von Ausdrücken
     mit der Funktion 'atensimp' angewendet wird.  Die Dimension wird
     von der Funktion 'init_atensor' initialisiert.  Ein indiziertes
     Symbol mit dem Bezeichner 'asymbol' ist dann ein Basisvektor, wenn
     der Index kleiner oder gleich der Dimension 'adim' ist.

     Beispiel:

     Die Dirac-Algebra hat die Dimension '4' und 'v[4]' ist ein
     Basisvektor.

          (%i1) load(atensor)$

          (%i2) init_atensor(dirac);
          (%o2)                         done
          (%i3) adim;
          (%o3)                           4
          (%i4) abasep(v[4]);
          (%o4)                         true

 -- Optionsvariable: aform
     Standardwert: 'ident(3)'

     Matrix mit den Werten der Bilinearformen 'sf', 'af' und 'av'.  Der
     Standardwert ist die dreidimensionale Einheitsmatrix.

     Beispiel:

     Das Beispiel zeigt die Matrix 'aform' für eine Lie-Algebra mit drei
     Dimensionen und die Ergebnisse der Bilinearform 'av' für diese
     Algebra.

          (%i1) load(atensor)$

          (%i2) init_atensor(lie_envelop, 3);
          (%o2)                         done
          (%i3) aform;
                                  [  0    3   - 2 ]
                                  [               ]
          (%o3)                   [ - 3   0    1  ]
                                  [               ]
                                  [  2   - 1   0  ]
          (%i4) av(v[1], v[2]);
          (%o4)                          v
                                          3
          (%i5) av(v[1], v[3]);
          (%o5)                         - v
                                           2

 -- Optionsvariable: asymbol
     Standardwert: 'v'

     Enthält das Symbol, das einen Basisvektor des Paketes 'atensor'
     bezeichnet.  Mit der Funktion 'abasep' kann getestet werde, ob ein
     indiziertes Symbol einen Basisvektor der Algebra bezeichnet.

     Beispiel:

     In diesem Beispiel wird 'asymbol' auf den Wert 'x' gesetzt.

          (%i1) load(atensor)$

          (%i2) init_atensor(symmetric, 2);
          (%o2)                         done
          (%i3) asymbol;
          (%o3)                           v
          (%i4) abasep(v[2]);
          (%o4)                         true
          (%i5) asymbol: x;
          (%o5)                           x
          (%i6) abasep(x[2]);
          (%o6)                         true

 -- Funktion: sf (<u>, <v>)

     Eine symmetrische Bilinearform, die bei der Vereinfachung von
     Ausdrücken mit der Funktion 'atensimp' angewendet wird.  Die
     Funktion kann vom Nutzer durch eine neue Funktion ersetzt werden.
     Die Standardimplementation prüft mit der Funktion 'abasep', ob die
     Argumente <u> und <v> Basisvektoren sind und setzt für diesen Fall
     den entsprechen Wert der Matrix 'aform' ein.

 -- Funktion: af (<u>, <v>)

     Eine antisymmetrische Bilinearform, die bei der Vereinfachung von
     Ausdrücken mit der Funktion 'atensimp' angewendet wird.  Die
     Funktion kann vom Nutzer durch eine neue Funktion ersetzt werden.
     Die Standardimplementation prüft mit der Funktion 'abasep', ob die
     Argumente <u> und <v> Basisvektoren sind und setzt für diesen Fall
     den entsprechenden Wert der Matrix 'aform' ein.

 -- Funktion: av (<u>, <v>)

     Eine antisymmetrische Bilinearform, die bei der Vereinfachung von
     Ausdrücken mit der Funktion 'atensimp' angewendet wird.  Die
     Funktion kann vom Nutzer durch eine neue Funktion ersetzt werden.
     Die Standardimplementation prüft mit der Funktion 'abasep', ob die
     Argumente <u> und <v> Basisvektoren sind und setzt für diesen Fall
     den entsprechenden Wert 'v[aform[i,j]]' der Matrix 'aform' ein.

     Beispiel:

          (%i1) load(atensor)$
          (%i2) adim: 3;
          (%o2)                           3
          (%i3) aform:matrix([0,3,-2],[-3,0,1],[2,-1,0]);
                                  [  0    3   - 2 ]
                                  [               ]
          (%o3)                   [ - 3   0    1  ]
                                  [               ]
                                  [  2   - 1   0  ]
          (%i4) asymbol: x;
          (%o4)                           x
          (%i5) av(x[1], x[2]);
          (%o5)                          x
                                          3
          (%i6) av(x[1], x[3]);
          (%o6)                         - x
                                           2

 -- Funktion: abasep (<v>)

     Prüft, ob das Argument <v> ein Basisvektor ist.  Ein Basisvektor
     ist ein indiziertes Symbol mit dem Symbol 'asymbol' als Bezeichner
     und einem Index im Bereich von '1' bis 'adim'.

     Beispiel:

          (%i1) load(atensor)$
          (%i2) asymbol: x$
          (%i3) adim:3$
          (%i4) abasep(x[1]);
          (%o4)                         true
          (%i5) abasep(x[3]);
          (%o5)                         true
          (%i6) abasep(x[4]);
          (%o6)                         false


File: maxima.info,  Node: Zahlentheorie,  Next: Spezielle Funktionen,  Prev: Tensoren,  Up: Top

21 Zahlentheorie
****************

* Menu:

* Funktionen und Variablen der Zahlentheorie::


File: maxima.info,  Node: Funktionen und Variablen der Zahlentheorie,  Prev: Zahlentheorie,  Up: Zahlentheorie

21.1 Funktionen und Variablen der Zahlentheorie
===============================================

 -- Funktion: bern (<n>)

     Gibt die <n>-te Bernoulli-Zahl der ganzen Zahl <n> zurück.  Hat die
     Optionsvariable 'zerobern' den Wert 'false', werden
     Bernoulli-Zahlen unterdrückt, die Null sind.

     Siehe auch 'burn'.

          (%i1) zerobern: true$
          (%i2) map (bern, [0, 1, 2, 3, 4, 5, 6, 7, 8]);
                            1  1       1      1        1
          (%o2)       [1, - -, -, 0, - --, 0, --, 0, - --]
                            2  6       30     42       30
          (%i3) zerobern: false$
          (%i4) map (bern, [0, 1, 2, 3, 4, 5, 6, 7, 8]);
                      1  1    1   5     691   7    3617  43867
          (%o4) [1, - -, -, - --, --, - ----, -, - ----, -----]
                      2  6    30  66    2730  6    510    798

 -- Funktion: bernpoly (<x>, <n>)

     Gibt das <n>-te Bernoulli-Polynom in der Variablen <x> zurück.

 -- Function: bfzeta (<s>, <n>)

     Die Riemannsche Zeta-Funktion für das Argument <s>, die wie folgt
     definiert ist:

                           inf
                           ====
                           \     1
               zeta(s) =    >    --
                           /      s
                           ====  k
                           k = 1

     'bfzeta' gibt einen Wert als große Gleitkommazahl zurück.  Die
     Anzahl der Stellen wird durch das Argument <n> angegeben.

     Anstatt der Funktion 'bfzeta' ist die Funktion 'zeta' zu
     bevorzugen, die sowohl für reelle und komplexe Gleitkommazahlen und
     Gleitkommazahlen mit eine beliebigen Genauigkeit die Riemannsche
     Zeta-Funktion berechnen kann.

 -- Funktion: bfhzeta (<s>, <h>, <n>)

     Die Hurwitzsche Zeta-Funktion für die Argumente <s> und <h>, die
     wie folgt definiert ist:

                                  inf
                                  ====
                                  \        1
                   zeta (s,h)  =   >    --------
                                  /            s
                                  ====  (k + h)
                                  k = 0

     'bfhzeta' gibt einen Wert als große Gleitkommazahl zurück.  Die
     Anzahl der Stellen wird durch das Argument <n> angegeben.

 -- Funktion: burn (<n>)

     Gibt eine rational Zahl zurück, die eine Näherung für die <n>-te
     Bernoulli Zahl für die ganze Zahl <n> ist.  'burn' berechnet eine
     Näherung als große Gleitkommatzahl mit der folgenden Beziehung:

                             n - 1  1 - 2 n
                        (- 1)      2        zeta(2 n) (2 n)!
               B(2 n) = ------------------------------------
                                          2 n
                                       %pi

     'burn' kann effizienter als die Funktion 'bern' für große, einzelne
     ganze Zahlen <n> sein, da 'bern' zunächst alle Bernoulli Zahlen bis
     <n> berechnet.  'burn' ruft für ungerade ganze Zahlen und Zahlen
     die kleiner oder gleich 255 die Funktion 'bern' auf.

     Das Kommando 'load(bffac)' lädt die Funktion.  Siehe auch 'bern'.

 -- Funktion: chinese ([<r_1>, ..., <r_n>], [<m_1>, ..., <m_n>])

     Löst die simultanen Kongruenzen 'x = r_1 mod m_1', ..., 'x = r_n
     mod m_n'.  Die Reste <r_n> und die Moduli <m_n> müssen ganze Zahlen
     sein, die Moduli zusätzlich positiv und paarweise teilerfremd.

          (%i1) mods : [1000, 1001, 1003, 1007];
          (%o1)                   [1000, 1001, 1003, 1007]
          (%i2) lreduce('gcd, mods);
          (%o2)                               1
          (%i3) x : random(apply("*", mods));
          (%o3)                         685124877004
          (%i4) rems : map(lambda([z], mod(x, z)), mods);
          (%o4)                       [4, 568, 54, 624]
          (%i5) chinese(rems, mods);
          (%o5)                         685124877004
          (%i6) chinese([1, 2], [3, n]);
          (%o6)                    chinese([1, 2], [3, n])
          (%i7) %, n = 4;
          (%o7)                              10

 -- Funktion: divsum (<n>, <k>)
 -- Funktion: divsum (<n>)

     'divsum(<n>, <k>)' potenziert die Teiler des Argumentes <n> mit dem
     Argument <k> und gibt die Summe als Ergebnis zurück.

     'divsum(<n>)' gibt die Summe der Teiler der Zahl <n> zurück.

          (%i1) divsum (12);
          (%o1)                          28
          (%i2) 1 + 2 + 3 + 4 + 6 + 12;
          (%o2)                          28
          (%i3) divsum (12, 2);
          (%o3)                          210
          (%i4) 1^2 + 2^2 + 3^2 + 4^2 + 6^2 + 12^2;
          (%o4)                          210

 -- Funktion: euler (<n>)

     Gibt die <n>-te Eulersche Zahl für eine nichtnegative ganze Zahl
     <n> zurück.

     Für die Euler-Mascheroni Konstante siehe '%gamma'.

     Beispiele:

          (%i1) map (euler, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
          (%o1)    [1, 0, - 1, 0, 5, 0, - 61, 0, 1385, 0, - 50521]

 -- Optionsvariable: factors_only
     Standardwert: 'false'

     Hat 'factors_only' den Standardwert 'false', werden von der
     Funktion 'ifactors' zusammen mit den berechneten Primfaktoren auch
     deren Multiplizitäten angegeben.  Hat 'factors_only' den Wert
     'true', werden nur die Primfaktoren zurück gegeben.

     Beispiel: Siehe 'ifactors'.

 -- Funktion: fib (<n>)

     Gibt die <n>-te Fibonacci-Zahl zurück.  Die Fibonacci-Folge ist
     rekursiv definiert:

             fib(0) = 0
             fib(1) = 1
             fib(n) = fib(n-1) + fib(n-2)

     Für negative ganze Zahlen kann die Fibonacci-Folge wie folgt
     erweitert werden:

                             n + 1
             fib(- n) = (- 1)      fib(n)

     Nach einem Aufruf der Funktion 'fib(n)', enthält die Systemvariable
     'prevfib' die zur Zahl 'n' vorhergehende Fibonacci-Zahl.

          (%i1) map (fib, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
          (%o1)         [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

 -- Funktion: fibtophi (<expr>)

     Fibonacci-Zahlen im Ausdruck <expr> werden durch die Goldene Zahl
     '%phi' ausgedrückt.  Siehe '%phi'.

     Beispiele:

          (%i1) fibtophi (fib (n));
                                     n             n
                                 %phi  - (1 - %phi)
          (%o1)                  -------------------
                                     2 %phi - 1
          (%i2) fib (n-1) + fib (n) - fib (n+1);
          (%o2)          - fib(n + 1) + fib(n) + fib(n - 1)
          (%i3) fibtophi (%);
                      n + 1             n + 1       n             n
                  %phi      - (1 - %phi)        %phi  - (1 - %phi)
          (%o3) - --------------------------- + -------------------
                          2 %phi - 1                2 %phi - 1
                                                    n - 1             n - 1
                                                %phi      - (1 - %phi)
                                              + ---------------------------
                                                        2 %phi - 1
          (%i4) ratsimp (%);
          (%o4)                           0

 -- Funktion: ifactors (<n>)

     Faktorisiert eine positive ganze Zahl <n>.  Sind 'n = p1^e1 * ... *
     pk^nk' die Faktoren der ganzen Zahl <n>, dann gibt 'ifactor' das
     Ergebnis '[[p1, e1], ..., [pk, ek]]' zurück.

     Für die Faktorisierung kommen Probedivisionen mit Primzahlen bis
     9973, Pollards Rho- und p-1-Methode oder Elliptischen Kurven zum
     Einsatz.

     Die Rückgabe von ifactors wird von der Optionsvariablen
     'factors_only' beeinflusst.  Werden lediglich die Primfaktoren ohne
     ihre Multiplizität benötigt, genügt es hierfür, 'factors_only :
     true' zu setzen.

          (%i1) ifactors(51575319651600);
          (%o1)     [[2, 4], [3, 2], [5, 2], [1583, 1], [9050207, 1]]
          (%i2) apply("*", map(lambda([u], u[1]^u[2]), %));
          (%o2)                        51575319651600
          (%i3) ifactors(51575319651600), factors_only : true;
          (%o3)                   [2, 3, 5, 1583, 9050207]

 -- Funktion: igcdex (<n>, <k>)

     Gibt die Liste '[a, b, u]' zurück, in der 'u' der größte gemeinsame
     Teiler von <n> und <k> ist und in der zusätzlich gilt, dass 'u = a
     * <n> + b * <k>'.

     'igcdex' verwendet den Euklidischen Algorithmus.  Siehe auch
     'gcdex'.

     Die Eingabe 'load(gcdex)' lädt diese Funktion.

     Beispiele:

          (%i1) load(gcdex)$

          (%i2) igcdex(30, 18);
          (%o2)                      [- 1, 2, 6]
          (%i3) igcdex(1526757668, 7835626735736);
          (%o3)            [845922341123, - 164826435, 4]
          (%i4) igcdex(fib(20), fib(21));
          (%o4)                   [4181, - 2584, 1]

 -- Funktion: inrt (<x>, <n>)

     Gibt die ganzzahlige <n>-te Wurzel des Betrags von <x> zurück.

          (%i1) l: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]$
          (%i2) map (lambda ([a], inrt (10^a, 3)), l);
          (%o2) [2, 4, 10, 21, 46, 100, 215, 464, 1000, 2154, 4641, 10000]

 -- Funktion: inv_mod (<n>, <m>)

     Berechnet das modulare Inverse von <n> zum Modul <m>.  Das Argument
     <n> muss eine ganze Zahl und der Modul <p> eine positive ganze Zahl
     sein.  'inv_mod(n, m)' gibt 'false' zurück, wenn das modulare
     Inverse nicht existiert.  Das modulare Inverse existiert, wenn <n>
     teilerfremd zum Modul <m> ist.

     Siehe auch die Funktionen 'power_mod' und 'mod'.

     Beispiele:

          (%i1) inv_mod(3, 41);
          (%o1)                           14
          (%i2) ratsimp(3^-1), modulus = 41;
          (%o2)                           14
          (%i3) inv_mod(3, 42);
          (%o3)                          false

 -- Funktion: isqrt (<x>)

     Gibt die ganzzahlige Wurzel des Betrages von <x> zurück, wenn <x>
     eine ganze Zahl ist.  Andernfalls wird eine Substantivform
     zurückgegeben.

 -- Funktion: jacobi (<p>, <q>)

     Berechnet das Jacobi-Symbol für die Argumente <p> und <q>.

          (%i1) l: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]$
          (%i2) map (lambda ([a], jacobi (a, 9)), l);
          (%o2)         [1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0]

 -- Funktion: lcm (<expr_1>, ..., <expr_n>)

     Gibt das kleinste gemeinsame Vielfache der Argumente zurück.  Die
     Argumente können ganze Zahlen und allgemeine Ausdrücke sein.

     Mit dem Kommando 'load(functs)' wird die Funktion geladen.

 -- Funktion: lucas (<n>)

     Gibt die <n>-te Lucas-Zahl zurück.  Die Lucas-Folge ist rekursiv
     definiert:

             lucas(0) = 0
             lucas(1) = 1
             lucas(n) = lucas(n-1) + lucas(n-2)

     Für negative ganze Zahlen kann die Lucas-Folge wie folgt erweitert
     werden:

                               -n
             lucas(- n) = (- 1)   lucas(n)

          (%i1) map (lucas, [-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8]);
          (%o1)             [7, - 4, 3, - 1, 2, 1, 3, 4, 7, 11, 18, 29, 47]

     Nach einem Aufruf von 'lucas' enthält die globale Variable
     'next_lucas' den Nachfolger der zuletzt zurc"k gegebenen
     Lucas-Zahl.  Das Beispiel zeigt, wie Fibonacci-Zahlen mit Hilfe von
     'lucas' und 'next_lucas' berechnet werden können.

          (%i1) fib_via_lucas(n) :=
                   block([lucas : lucas(n)],
                   signum(n) * (2*next_lucas - lucas)/5 )$
          (%i2) map (fib_via_lucas, [-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8]);
          (%o2)             [- 3, 2, - 1, 1, 0, 1, 1, 2, 3, 5, 8, 13, 21]

 -- Funktion: mod (<x>, <p>)

     Berechnet den Divisionsrest 'x mod y' des Arguments <x> zum Modul
     <y>.  <x> und <y> können ganze Zahlen, rationale Zahlen,
     Gleitkommazahlen oder allgemeine Ausdrücke sein.

     Sind <x> und <y> reelle Zahlen und ist <y> ungleich Null, gibt
     'mod(<x>, <y>)' das Ergebnis von '<x> - <y> * floor(<x> / <y>)'
     zurück.  Weiterhin gilt für alle reellen Zahlen 'mod(<x>, 0) =
     <x>'.  Für eine Diskussion dieser Definition siehe Kapitel 3.4,
     "Concrete Mathematics" von Graham, Knuth, and Patashnik.  Die
     Funktion 'mod(<x>, 1)' ist eine Sägezahnfunktion mit der Periode 1
     mit 'mod(1, 1) = 0' und 'mod(0, 1) = 0'.

     Der Hauptwert einer komplexen Zahl, die im Intervall '(-%pi, %pi)'
     liegt, kann mit '%pi - mod(%pi - <x>, 2*%pi)' bestimmt werden,
     wobei <x> die komplexe Zahl ist.

     Sind <x> und <y> konstante Ausdrücke, wie zum Beispiel '10 * %pi',
     verwendet 'mod' dasselbe 'bfloat'-Auswertungsschema wie 'floor' und
     'ceiling'.  Diese Umwandlung kann, wenn auch unwahrscheinlich, zu
     Fehlern führen.

     Für nicht numerische Argumente <x> oder <y> kennt 'mod'
     verschiedene Vereinfachungen.

     Siehe auch die Funktionen 'power_mod' und 'inv_mod'.

     Beispiele:

     Zeige für zwei große ganze Zahlen, dass für das modulare Rechnen
     die Regel 'mod(a+b, m) = mod(mod(a, m) + mod(b, m), m)' gilt.

          (%i1) a : random(10^20) + 10^19;
          (%o1)                 72588919020045581148
          (%i2) b : random(10^20) + 10^19;
          (%o2)                 35463666253140008825
          (%i3) m : random(10^20) + 10^19;
          (%o3)                 39127433614020247557
          (%i4) mod(a+b, m);
          (%o4)                 29797718045145094859
          (%i5) mod(mod(a, m) + mod(b, m), m);
          (%o5)                 29797718045145094859

     Vereinfachung für nicht numerische Argumente.

          (%i1) mod (x, 0);
          (%o1)                           x
          (%i2) mod (a*x, a*y);
          (%o2)                      a mod(x, y)
          (%i3) mod (0, x);
          (%o3)                           0

 -- Funktion: next_prime (<n>)

     Gibt die kleinste Primzahl zurück, die der Zahl <n> folgt.

          (%i1) next_prime(27);
          (%o1)                       29

 -- Funktion: power_mod (<a>, <n>, <m>)

     Verwendet einen modularen Algorithmus, um 'a^n mod m' zu berechnen.
     Die Argumente <a> und <n> müssen ganze Zahlen und der Modul <m>
     eine positive ganze Zahl sein.  Ist <n> negativ, wird 'inv_mod' zur
     Berechnung des modularen Inversen aufgerufen.

     'power_mod (<a>, <n>, <m>)' ist äquivalent zu 'mod(a^n, m)'.  Der
     Algorithmus von 'power_mod' ist jedoch insbesondere für große ganze
     Zahlen wesentlich effizienter.

     Siehe auch die Funktionen 'inv_mod' und 'mod'.

     Beispiele:

     'power_mod(a, n, m)' ist äquivalent zu 'mod(a^n, m'.  Das modulare
     Inverse wird mit der Funktion 'inv_mod' berechnet.

          (%i1) power_mod(3, 15, 5);
          (%o1)                          2
          (%i2) mod(3^15, 5);
          (%o2)                          2
          (%i3) power_mod(2, -1, 5);
          (%o3)                          3
          (%i4) inv_mod(2, 5);
          (%o4)                          3

     Für große ganze Zahlen ist 'power_mod' effizienter.  Der folgende
     Wert kann in keiner vernünftigen Zeit mit 'mod(a^n, m)' berechnet
     werden.

          (%i1) power_mod(123456789, 123456789, 987654321);
          (%o1)                       598987215

 -- Funktion: primep (<n>)

     Führt einen Primzahltest für das Argument <n> durch.  Liefert
     'primep' das Ergebnis 'false', ist <n> keine Primzahl.  Ist das
     Ergebnis 'true', ist <n> mit sehr großer Wahrscheinlichkeit eine
     Primzahl.

     Für ganze Zahlen <n> kleiner als 341550071728321 wird eine
     deterministische Variante des Miller-Rabin-Tests angewandt.  Hat in
     diesem Fall 'primep' den Wert 'true', dann ist <n> mit Sicherheit
     eine Primzahl.

     Für ganze Zahlen <n> größer 341550071728321 führt 'primep'
     'primep_number_of_tests' Pseudo-Primzahl-Tests nach Miller-Rabin
     und einen Pseudo-Primzahl-Test nach Lucas durch.  Die
     Wahrscheinlichkeit, dass eine zusammen gesetzte Zahl <n> einen
     Miller-Rabin-Test besteht, ist kleiner als 1/4.  Mit dem
     Standardwert 25 'primpe_number_of_tests' sinkt diese
     Wahrscheinlichkeit damit unter einen Wert von 10^-15.

 -- Optionsvariable: primep_number_of_tests
     Standardwert: 25

     Die Anzahl der Pseudo-Primzahl-Tests nach Miller-Rabin in der
     Funktion 'primep'.

 -- Funktion: primes (<start>, <end>)

     Gibt eine Liste mit allen Primzahlen von <start> bis <end> zurück.

          (%i1) primes(3, 7);
          (%o1)                     [3, 5, 7]

 -- Funktion: prev_prime (<n>)

     Gibt die größte Primzahl zurück, die kleiner als die Zahl <n> ist.

          (%i1) prev_prime(27);
          (%o1)                       23

 -- Funktion: qunit (<n>)

     Findet für das Argument <n> Lösungen der Pellschen Gleichung 'a^2 -
     <n> b^2 = 1'.

          (%i1) qunit (17);
          (%o1)                     sqrt(17) + 4
          (%i2) expand (% * (sqrt(17) - 4));
          (%o2)                           1

 -- Funktion: totient (<n>)

     Gibt die Anzahl der ganzen Zahlen zurück, die kleiner oder gleich
     <n> und teilerfremd zu <n> sind.

 -- Optionsvariable: zerobern
     Standardwert: 'true'

     Hat 'zerobern' den Wert 'false', werden von den Funktionen 'bern'
     diejenigen Bernoulli-Zahlen und von 'euler' diejenigen Euler-Zahlen
     ausgeschlossen, die gleich Null sind.  Siehe 'bern' und 'euler'.

 -- Funktion: zeta (<n>)

     Die Riemannsche Zeta-Funktion für <s>, die wie folgt definiert ist:

                           inf
                           ====
                           \     1
               zeta(s) =    >    --
                           /      s
                           ====  k
                           k = 1

     Für negative ganze Zahlen <n>, Null und positive gerade ganze
     Zahlen wird 'zeta' zu einem exakten Ergebnis vereinfacht.  Damit
     diese Vereinfachung für positive ganze Zahlen ausgeführt wird, muss
     die Optionsvariable 'zeta%pi' den Wert 'true' haben.  Siehe
     'zeta%pi'.  Für einfache und beliebig genaue Gleitkommazahlen (Typ
     'bfloat') hat 'zeta' ein numerisches Ergebnis.  Für alle anderen
     Argumente einschließlich der komplexen und rationalen Zahlen gibt
     'zeta' eine Substantivform zurück.  Hat die Optionsvariable
     'zeta%pi' den Wert 'false', gibt 'zeta' auch für gerade ganze
     Zahlen eine Substantivform zurück.

     'zeta(1)' ist nicht definiert.  Maxima kennt jedoch die einseitigen
     Grenzwerte 'limit(zeta(x), x, 1, plus' und 'limit(zeta(x), x, 1,
     minus'.

     Die Riemannsche Zeta-Funktion wird auf die Argumente von Listen,
     Matrizen und Gleichungen angewendet, wenn die Optionsvariable
     'distribute_over' den Wert 'true' hat.

     Siehe auch 'bfzeta' und 'zeta%pi'.

     Beispiele:

          (%i1) zeta([-2,-1,0,0.5,2,3,1+%i]);
                                                       2
                      1     1                       %pi
          (%o1) [0, - --, - -, - 1.460354508809586, ----, zeta(3),
                      12    2                        6
                                                              zeta(%i + 1)]
          (%i2) limit(zeta(x),x,1,plus);
          (%o2)                          inf
          (%i3) limit(zeta(x),x,1,minus);
          (%o3)                         minf

 -- Optionsvariable: zeta%pi
     Standardwert: 'true'

     Hat 'zeta%pi' den Wert 'true', vereinfacht die Funktion 'zeta(n)'
     für gerade ganzen Zahlen <n> zu einem Ergebnis, das proportional zu
     '%pi^n' ist.  Ansonsten ist das Ergebnis von 'zeta' eine
     Substantivform für gerade ganze Zahlen.

     Beispiele:

          (%i1) zeta%pi: true$
          (%i2) zeta (4);
                                           4
                                        %pi
          (%o2)                         ----
                                         90
          (%i3) zeta%pi: false$
          (%i4) zeta (4);
          (%o4)                        zeta(4)

 -- Funktion: zn_add_table (<n>)

     zeigt eine Additionstabelle von allen Elementen in (Z/<n>Z).

     Siehe auch 'zn_mult_table', 'zn_power_table'.

 -- Funktion: zn_characteristic_factors (<n>)

     Gibt eine Liste mit den charakteristischen Faktoren des Totienten
     von <n> zurück.

     Mit Hilfe der charakteristischen Faktoren kann eine modulo <n>
     multiplikative Gruppe als direktes Produkt zyklischer Untergruppen
     dargestellt werden.

     Ist die Gruppe selbst zyklisch, dann enthält die Liste nur den
     Totienten und mit 'zn_primroot' kann ein Generator berechnet
     werden.  Zerfällt der Totient in mehrere charakteristische
     Faktoren, können Generatoren der entsprechenden Untergruppen mit
     'zn_factor_generators' ermittelt werden.

     Jeder der 'r' Faktoren in der Liste teilt die weiter rechts
     stehenden Faktoren.  Fuer den letzten Faktor 'f_r' gilt daher
     'a^f_r = 1 (mod n)' für alle 'a' teilerfremd zu <n>.  Dieser Faktor
     ist auch als Carmichael Funktion bzw.  Carmichael Lambda bekannt.

     Für 'n > 2' ist 'totient(n)/2^r' die Anzahl der quadratischen Reste
     in der Gruppe und jeder dieser Reste hat '2^r' Wurzeln.

     Siehe auch 'totient', 'zn_primroot', 'zn_factor_generators'.

     Beispiele:

     Die multiplikative Gruppe modulo '14' ist zyklisch und ihre '6'
     Elemente lassen sich durch eine Primitivwurzel erzeugen.

          (%i1) [zn_characteristic_factors(14), phi: totient(14)];
          (%o1)                              [[6], 6]
          (%i2) [zn_factor_generators(14), g: zn_primroot(14)];
          (%o2)                              [[3], 3]
          (%i3) M14: makelist(power_mod(g,i,14), i,0,phi-1);
          (%o3)                         [1, 3, 9, 13, 11, 5]

     Die multiplikative Gruppe modulo '15' ist nicht zyklisch und ihre
     '8' Elemente lassen sich mit Hilfe zweier Faktorgeneratoren
     erzeugen.

          (%i1) [[f1,f2]: zn_characteristic_factors(15), totient(15)];
          (%o1)                             [[2, 4], 8]
          (%i2) [[g1,g2]: zn_factor_generators(15), zn_primroot(15)];
          (%o2)                           [[11, 7], false]
          (%i3) UG1: makelist(power_mod(g1,i,15), i,0,f1-1);
          (%o3)                               [1, 11]
          (%i4) UG2: makelist(power_mod(g2,i,15), i,0,f2-1);
          (%o4)                            [1, 7, 4, 13]
          (%i5) M15: create_list(mod(i*j,15), i,UG1, j,UG2);
          (%o5)                      [1, 7, 4, 13, 11, 2, 14, 8]

     Für den letzten charakteristischen Faktor '4' gilt 'a^4 = 1 (mod
     15)' fuer alle 'a' in 'M15'.

     'M15' hat '2' charakteristische Faktoren und daher die '8/2^2'
     quadratischen Reste '1' und '4', und diese haben jeweils '2^2'
     Wurzeln.

          (%i6) zn_power_table(15);
                                         [ 1   1  1   1 ]
                                         [              ]
                                         [ 2   4  8   1 ]
                                         [              ]
                                         [ 4   1  4   1 ]
                                         [              ]
                                         [ 7   4  13  1 ]
          (%o6)                          [              ]
                                         [ 8   4  2   1 ]
                                         [              ]
                                         [ 11  1  11  1 ]
                                         [              ]
                                         [ 13  4  7   1 ]
                                         [              ]
                                         [ 14  1  14  1 ]
          (%i7) map(lambda([i], zn_nth_root(i,2,15)), [1,4]);
          (%o7)                   [[1, 4, 11, 14], [2, 7, 8, 13]]

 -- Funktion: zn_carmichael_lambda (<n>)

     Gibt '1' zurück, wenn <n> gleich '1' ist und andernfalls den
     größten charakteristischen Faktor des Totienten von <n>.

     Für Erläuterungen und Beispiele siehe 'zn_characteristic_factors'.

 -- Funktion: zn_determinant (<matrix>, <p>)

     verwendet die Technik der LR-Dekomposition, um die Determinante der
     Matrix <matrix> über (Z/<p>Z) zu berechnen, wobei <p> eine Primzahl
     sein muss.

     Ist die Determinante nicht von Null verschieden, kann es sein, dass
     die LR-Dekomposition nicht möglich ist.  'zn_determinant' berechnet
     diesem Fall die Determinante nicht-modular und reduziert im
     Nachhinein.

     Siehe auch 'zn_invert_by_lu'.

     Beispiel:

          (%i1) m : matrix([1,3],[2,4]);
                                          [ 1  3 ]
          (%o1)                           [      ]
                                          [ 2  4 ]
          (%i2) zn_determinant(m, 5);
          (%o2)                               3
          (%i3) m : matrix([2,4,1],[3,1,4],[4,3,2]);
                                         [ 2  4  1 ]
                                         [         ]
          (%o3)                          [ 3  1  4 ]
                                         [         ]
                                         [ 4  3  2 ]
          (%i4) zn_determinant(m, 5);
          (%o4)                               0

 -- Funktion: zn_factor_generators (<n>)

     Gibt eine Liste mit Faktorgeneratoren zurück, die zu den
     charakteristischen Faktoren des Totienten von <n> passen.

     Für Erläuterungen und Beispiele siehe 'zn_characteristic_factors'.

 -- Funktion: zn_invert_by_lu (<matrix>, <p>)

     verwendet die Technik der LR-Dekomposition, um ein modulares
     Inverses der Matrix <matrix> über (Z/<p>Z) zu berechnen.
     Voraussetzung ist, dass <matrix> invertierbar und <p> eine Primzahl
     ist.  Sollte <matrix> nicht invertierbar sein, gibt
     'zn_invert_by_lu' 'false' zurc"k.

     Siehe auch 'zn_determinant'.

     Beispiele:

          (%i1) m : matrix([1,3],[2,4]);
                                          [ 1  3 ]
          (%o1)                           [      ]
                                          [ 2  4 ]
          (%i2) zn_determinant(m, 5);
          (%o2)                               3
          (%i3) mi : zn_invert_by_lu(m, 5);
                                          [ 3  4 ]
          (%o3)                           [      ]
                                          [ 1  2 ]
          (%i4) matrixmap(lambda([a], mod(a, 5)), m . mi);
                                          [ 1  0 ]
          (%o4)                           [      ]
                                          [ 0  1 ]

 -- Funktion: zn_log (<a>, <g>, <n>)
 -- Funktion: zn_log (<a>, <g>, <n>, [[<p1>, <e1>], ..., [<pk>, <ek>]])

     Berechnet den diskreten Logarithmus.  Sei (Z/<n>Z)* eine zyklische
     Gruppe, <g> eine Primitivwurzel modulo <n> und <a> ein Element
     dieser Gruppe.  Dann berechnet 'zn_log (a, g, n)' eine Lösung der
     Kongruenz 'g^x = a mod n'.

     Der verwendete Algorithmus benötigt die Primfaktorzerlegung des
     Totienten von <n>.  Da diese Berechnung ebenfalls zeitaufwändig
     ist, kann es eventuell sinnvoll sein, die Primfaktoren des
     Totienten vorab zu berechnen und 'zn_log' als viertes Argument zu
     übergeben.  Die Form muss dabei der Rückgabe von
     'ifactors(totient(n))' mit der Standardeinstellung 'false' der
     Optionsvariable 'factors_only' entsprechen.

     Als Algorithmus wird die Pohlig-Hellman-Reduktion und das
     Rho-Verfahren von Pollard für den diskreten Logarithmus verwendet.
     Die Laufzeit von 'zn_log' hängt im Wesentlichen von der Bitlänge
     des größten Primfaktors des Totienten von <n> ab.

     Siehe auch 'zn_primroot', 'zn_order', 'ifactors', 'totient'.

     Beispiele:

     'zn_log (a, g, n)' findet eine Lösung der Kongruenz 'g^x = a mod
     n'.

          (%i1) n : 22$
          (%i2) g : zn_primroot(n);
          (%o2)                               7
          (%i3) ord_7 : zn_order(7, n);
          (%o3)                              10
          (%i4) powers_7 : makelist(power_mod(g, x, n), x, 0, ord_7 - 1);
          (%o4)              [1, 7, 5, 13, 3, 21, 15, 17, 9, 19]
          (%i5) zn_log(21, g, n);
          (%o5)                               5
          (%i6) map(lambda([x], zn_log(x, g, n)), powers_7);
          (%o6)                [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

     Das optionale vierte Argument muss der Rückgabe von
     'ifactors(totient(n))' entsprechen.  Die Laufzeit hängt im
     Wesentlichen von der Bitlänge des größten Primfaktors des Totienten
     ab.

          (%i1) (p : 2^127-1, primep(p));
          (%o1)                             true
          (%i2) ifs : ifactors(p - 1)$
          (%i3) g : zn_primroot(p, ifs);
          (%o3)                              43
          (%i4) a : power_mod(g, 1234567890, p)$
          (%i5) zn_log(a, g, p, ifs);
          (%o5)                          1234567890
          (%i6) time(%o5);
          (%o6)                            [1.204]
          (%i7) f_max : last(ifs);
          (%o7)                       [77158673929, 1]
          (%i8) slength( printf(false, "~b", f_max[1]) );
          (%o8)                              37

 -- Funktion: zn_mult_table (<n>)
 -- Funktion: zn_mult_table (<n>, <gcd>)

     Ohne das optionale Argument <gcd> zeigt 'zn_mult_table(n)' eine
     Multiplikationstabelle von allen Elementen in (Z/<n>Z)*, d.h.  von
     allen zu <n> teilerfremden Elementen.

     Das optionale zweite Argument <gcd> erlaubt es, eine bestimmte
     Untermenge von (Z/<n>Z) auszuwählen.  Ist <gcd> eine natürliche
     Zahl, enthält die Multiplikationstabelle alle Restklassen 'x' mit
     'gcd(x,n) = '<gcd>.  Zur besseren Lesbarkeit werden Zeilen- und
     Spaltenköpfe hinzugefügt.  Falls notwendig, lassen sich diese mit
     'submatrix(1, tabelle, 1)' wieder einfach entfernen.

     Wird <gcd> auf 'all' gesetzt, wird die Tabelle für sämtliche von
     Null verschiedene Elemente in (Z/<n>Z) ausgegeben.

     Das zweite Beispiel unten zeigt einen alternativen Weg, für
     Untergruppen eine Multiplikationstabelle zu erzeugen.

     Siehe auch 'zn_add_table', 'zn_power_table'.

     Beispiele:

     Die Standardtabelle zeigt alle Elemente aus (Z/<n>Z)* und erlaubt,
     grundlegende Eigenschaften von modularen Multiplikationsgruppen zu
     zeigen und zu studieren.  Z.B. stehen in der Hauptdiagonale
     sämtliche quadratische Reste, jede Zeile und Spalte enthält alle
     Elemente, die Tabelle ist symmetrisch, etc..

     Wird <gcd> auf 'all' gesetzt, wird die Tabelle für sämtliche von
     Null verschiedene Elemente in (Z/<n>Z) ausgegeben.

          (%i1) zn_mult_table(8);
                                          [ 1  3  5  7 ]
                                          [            ]
                                          [ 3  1  7  5 ]
          (%o1)                           [            ]
                                          [ 5  7  1  3 ]
                                          [            ]
                                          [ 7  5  3  1 ]
          (%i2) zn_mult_table(8, all);
                                      [ 1  2  3  4  5  6  7 ]
                                      [                     ]
                                      [ 2  4  6  0  2  4  6 ]
                                      [                     ]
                                      [ 3  6  1  4  7  2  5 ]
                                      [                     ]
          (%o2)                       [ 4  0  4  0  4  0  4 ]
                                      [                     ]
                                      [ 5  2  7  4  1  6  3 ]
                                      [                     ]
                                      [ 6  4  2  0  6  4  2 ]
                                      [                     ]
                                      [ 7  6  5  4  3  2  1 ]

     Ist <gcd> eine Zahl, wird zur besseren Lesbarkeit ein Zeilen- und
     Spaltenkopf hinzugefügt.

     Ist die mit <gcd> ausgewählte Teilmenge eine Gruppe, gibt es einen
     alternativen Weg, die Multiplikationstabelle zu erzeugen.  Die
     Isomorphie zu einer Gruppe mit '1' als Identität lässt sich nutzen,
     um eine leicht lesbare Tabelle zu erhalten.  Die Abbildung gelingt
     mit dem CRT.

     In der so erzeugten zweiten Version der Tabelle 'T36_4' steht genau
     wie bei 'T9' die Identität, hier '28', in der linken oberen Ecke.

          (%i1) T36_4: zn_mult_table(36,4);
                                  [ *   4   8   16  20  28  32 ]
                                  [                            ]
                                  [ 4   16  32  28  8   4   20 ]
                                  [                            ]
                                  [ 8   32  28  20  16  8   4  ]
                                  [                            ]
          (%o1)                   [ 16  28  20  4   32  16  8  ]
                                  [                            ]
                                  [ 20  8   16  32  4   20  28 ]
                                  [                            ]
                                  [ 28  4   8   16  20  28  32 ]
                                  [                            ]
                                  [ 32  20  4   8   28  32  16 ]
          (%i2) T9: zn_mult_table(36/4);
                                       [ 1  2  4  5  7  8 ]
                                       [                  ]
                                       [ 2  4  8  1  5  7 ]
                                       [                  ]
                                       [ 4  8  7  2  1  5 ]
          (%o2)                        [                  ]
                                       [ 5  1  2  7  8  4 ]
                                       [                  ]
                                       [ 7  5  1  8  4  2 ]
                                       [                  ]
                                       [ 8  7  5  4  2  1 ]
          (%i3) T36_4: matrixmap(lambda([x], chinese([0,x],[4,9])), T9);
                                    [ 28  20  4   32  16  8  ]
                                    [                        ]
                                    [ 20  4   8   28  32  16 ]
                                    [                        ]
                                    [ 4   8   16  20  28  32 ]
          (%o3)                     [                        ]
                                    [ 32  28  20  16  8   4  ]
                                    [                        ]
                                    [ 16  32  28  8   4   20 ]
                                    [                        ]
                                    [ 8   16  32  4   20  28 ]

 -- Funktion: zn_nth_root (<x>, <n>, <m>)
 -- Funktion: zn_nth_root (<x>, <n>, <m>, [[<p1>, <e1>], ..., [<pk>,
          <ek>]])

     Gibt eine Liste mit allen <n>-ten Wurzeln von <x> aus der
     multiplikativen Untergruppe von (Z/<m>Z) zurück, in der sich <x>
     befindet, oder 'false', falls <x> keine <n>-te Potenz modulo <m>
     oder kein Element einer multiplikativen Untergruppe von (Z/<m>Z)
     ist.

     <x> ist Element einer multiplikativen Untergruppe modulo <m>, wenn
     der größte gemeinsame Teiler 'g = gcd(x,m)' zu 'm/g' teilerfremd
     ist.

     'zn_nth_root' basiert auf einem Algorithmus von Adleman, Manders
     und Miller und Sätzen über modulare Multiplikationsgruppen von
     Daniel Shanks.

     Der Algorithmus benötigt eine Primfaktorzerlegung des Modulus <m>.
     Es kann eventuell sinnvoll sein, diese Zerlegung vorab zu berechnen
     und als viertes Argument zu übergeben.  Die Form muss dabei der
     Rückgabe von 'ifactors(m)' mit der Standardeinstellung 'false' der
     Optionsvariable 'factors_only' entsprechen.

     Beispiele:

     Eine Potenztabelle der multiplikativen Gruppe modulo '14' gefolgt
     von einer Liste mit Listen von <n>-ten Wurzeln der '1', wobei <n>
     von '1' bis '6' variiert.

          (%i1) zn_power_table(14);
                                   [ 1   1   1   1   1   1 ]
                                   [                       ]
                                   [ 3   9   13  11  5   1 ]
                                   [                       ]
                                   [ 5   11  13  9   3   1 ]
          (%o1)                    [                       ]
                                   [ 9   11  1   9   11  1 ]
                                   [                       ]
                                   [ 11  9   1   11  9   1 ]
                                   [                       ]
                                   [ 13  1   13  1   13  1 ]
          (%i2) makelist(zn_nth_root(1,n,14), n,1,6);
          (%o2)  [[1], [1, 13], [1, 9, 11], [1, 13], [1], [1, 3, 5, 9, 11, 13]]

     Im folgenden Beispiel ist <x> nicht zu <m> teilerfremd, aber es ist
     Element einer multiplikativen Untergruppe von (Z/<m>Z) und jede
     <n>-te Wurzel ist aus der selben Untergruppe.

     Die Restklasse '3' ist kein Element in irgend einer multiplikativen
     Untergruppe von (Z/63Z) und wird daher nicht als dritte Wurzel von
     '27' zurück gegeben.

     Hier zeigt 'zn_power_table' alle Reste 'x' in (Z/63Z) mit
     'gcd(x,63) = 9'.  Diese Untergruppe ist isomorph zu (Z/7Z)* und
     seine Identität '36' wird mit Hilfe des CRT berechnet.

          (%i1) m: 7*9$

          (%i2) zn_power_table(m,9);
                                   [ 9   18  36  9   18  36 ]
                                   [                        ]
                                   [ 18  9   36  18  9   36 ]
                                   [                        ]
                                   [ 27  36  27  36  27  36 ]
          (%o2)                    [                        ]
                                   [ 36  36  36  36  36  36 ]
                                   [                        ]
                                   [ 45  9   27  18  54  36 ]
                                   [                        ]
                                   [ 54  18  27  9   45  36 ]
          (%i3) zn_nth_root(27,3,m);
          (%o3)                           [27, 45, 54]
          (%i4) id7:1$  id63_9: chinese([id7,0],[7,9]);
          (%o5)                                36

     Im folgenden RSA-ähnlichen Beispiel, in dem der Modulus 'N'
     quadratfrei ist, d.h.  in paarweise verschiedene Primfaktoren
     zerfällt, ist jedes 'x' von '0' bis 'N-1' in einer multiplikativen
     Untergruppe enthalten.

     Zur Entschlüsselung wird die 'e'-te Wurzel berechnet.  'e' ist
     teilerfremd zu 'N' und die 'e'-te Wurzel ist deshalb eindeutig.
     'zn_nth_root' wendet hier effektiv den als CRT-RSA bekannten
     Algorithmus an.  (Man beachte, dass 'flatten' Klammern entfernt und
     keine Lösungen.)

          (%i1) [p,q,e]: [5,7,17]$  N: p*q$

          (%i3) xs: makelist(x,x,0,N-1)$

          (%i4) ys: map(lambda([x],power_mod(x,e,N)),xs)$

          (%i5) zs: flatten(map(lambda([y], zn_nth_root(y,e,N)), ys))$

          (%i6) is(zs = xs);
          (%o6)                             true

     Im folgenden Beispiel ist die Faktorisierung des Modulus bekannt
     und wird als viertes Argument übergeben.

          (%i1) p: 2^107-1$  q: 2^127-1$  N: p*q$

          (%i4) ibase: obase: 16$

          (%i5) msg: 11223344556677889900aabbccddeeff$

          (%i6) enc: power_mod(msg, 10001, N);
          (%o6)    1a8db7892ae588bdc2be25dd5107a425001fe9c82161abc673241c8b383
          (%i7) zn_nth_root(enc, 10001, N, [[p,1],[q,1]]);
          (%o7)               [11223344556677889900aabbccddeeff]

 -- Funktion: zn_order (<x>, <n>)
 -- Funktion: zn_order (<x>, <n>, [[<p1>, <e1>], ..., [<pk>, <ek>]])

     Ist <x> eine Einheit in der endlichen Gruppe (Z/<n>Z)*, so
     berechnet 'zn_order' die Ordnung dieses Elements.  Andernfalls gibt
     'zn_order' 'false' zurück.  <x> ist eine Einheit modulo <n>, falls
     <x> teilerfremd zu <n> ist.

     Der verwendete Algorithmus benötigt die Primfaktorzerlegung des
     Totienten von <n>.  Da diese Berechnung manchmal recht
     zeitaufwändig ist, kann es eventuell sinnvoll sein, die
     Primfaktoren des Totienten vorab zu berechnen und 'zn_order' als
     drittes Argument zu übergeben.  Die Form muss dabei der Rückgabe
     von 'ifactors(totient(n))' mit der Standardeinstellung 'false' der
     Optionsvariable 'factors_only' entsprechen.

     Siehe auch 'zn_primroot', 'ifactors', 'totient'.

     Beispiele:

     'zn_order' berechnet die Ordnung einer Einheit <x> aus (Z/<n>Z)*.

          (%i1) n : 22$
          (%i2) g : zn_primroot(n);
          (%o2)                               7
          (%i3) units_22 : sublist(makelist(i,i,1,21), lambda([x], gcd(x, n) = 1));
          (%o3)              [1, 3, 5, 7, 9, 13, 15, 17, 19, 21]
          (%i4) (ord_7 : zn_order(7, n)) = totient(n);
          (%o4)                            10 = 10
          (%i5) powers_7 : makelist(power_mod(g,i,n), i,0,ord_7 - 1);
          (%o5)              [1, 7, 5, 13, 3, 21, 15, 17, 9, 19]
          (%i6) map(lambda([x], zn_order(x, n)), powers_7);
          (%o6)              [1, 10, 5, 10, 5, 2, 5, 10, 5, 10]
          (%i7) map(lambda([x], ord_7/gcd(x, ord_7)), makelist(i, i,0,ord_7 - 1));
          (%o7)              [1, 10, 5, 10, 5, 2, 5, 10, 5, 10]
          (%i8) totient(totient(n));
          (%o8)                               4

     Das optionale dritte Argument muss der Rückgabe von
     'ifactors(totient(n))' entsprechen.

          (%i1) (p : 2^142 + 217, primep(p));
          (%o1)                             true
          (%i2) ifs : ifactors( totient(p) )$
          (%i3) g : zn_primroot(p, ifs);
          (%o3)                               3
          (%i4) is( (ord_3 : zn_order(g, p, ifs)) = totient(p) );
          (%o4)                             true
          (%i5) map(lambda([x], ord_3/zn_order(x, p, ifs)), makelist(i,i,2,15));
          (%o5)        [22, 1, 44, 10, 5, 2, 22, 2, 8, 2, 1, 1, 20, 1]

 -- Funktion: zn_power_table (<n>)
 -- Funktion: zn_power_table (<n>, <gcd>)
 -- Funktion: zn_power_table (<n>, <gcd>, <max_exp>)

     Ohne ein optionales Argument zeigt 'zn_power_table(n)' eine
     Potenzierungstabelle von allen Elementen in (Z/<n>Z)*, d.h.  von
     allen zu <n> teilerfremden Elementen.  Der Exponent variiert dabei
     jeweils zwischen '1' und dem größten charakteristischen Faktor des
     Totienten von <n> (auch bekannt als Carmichael Funktion bzw.
     Carmichael Lambda), so dass die Tabelle rechts mit einer Spalte von
     Einsen endet.

     Das optionale zweite Argument <gcd> erlaubt es, eine bestimmte
     Untermenge von (Z/<n>Z) auszuwählen.  Ist <gcd> eine natürliche
     Zahl, werden Potenzen von allen Restklassen 'x' mit 'gcd(x,n) =
     '<gcd> zurück gegeben, d.h.  <gcd> ist standardmäßig '1'.  Wird
     <gcd> auf 'all' gesetzt, wird die Tabelle für sämtliche Elemente in
     (Z/<n>Z) ausgegeben.

     Wird das optionale dritte Argument <max_exp> angegeben, variiert
     der Exponent zwischen '1' und <max_exp>.

     Siehe auch 'zn_add_table', 'zn_mult_table'.

     Beispiele:

     Die Standardeinstellung <gcd>' = 1' erlaubt es, grundlegende Sätze,
     wie die von Fermat and Euler, zu zeigen und zu betrachten.

     Das Argument <gcd> erlaubt es, bestimmte Teilmengen von (Z/<n>Z)
     auszuwählen und multiplikative Untergruppen und Isomorphismen zu
     untersuchen.

     Z.B. sind die Gruppen 'G10' und 'G10_2' unter der Multiplikation
     beide isomorph zu 'G5'.  '1' ist die Identität in 'G5'.  So sind
     '1' bzw.  '6' die Identitäten in 'G10' bzw.  'G10_2'.
     Entsprechende Zuordnungen ergeben sich bei den Primitivwurzeln,
     n-ten Wurzeln, etc..

          (%i1) zn_power_table(10);
                                        [ 1  1  1  1 ]
                                        [            ]
                                        [ 3  9  7  1 ]
          (%o1)                         [            ]
                                        [ 7  9  3  1 ]
                                        [            ]
                                        [ 9  1  9  1 ]
          (%i2) zn_power_table(10,2);
                                        [ 2  4  8  6 ]
                                        [            ]
                                        [ 4  6  4  6 ]
          (%o2)                         [            ]
                                        [ 6  6  6  6 ]
                                        [            ]
                                        [ 8  4  2  6 ]
          (%i3) zn_power_table(10,5);
          (%o3)                         [ 5  5  5  5 ]
          (%i4) zn_power_table(10,10);
          (%o4)                         [ 0  0  0  0 ]
          (%i5) G5: [1,2,3,4];
          (%o6)                          [1, 2, 3, 4]
          (%i6) G10_2: map(lambda([x], chinese([0,x],[2,5])), G5);
          (%o6)                          [6, 2, 8, 4]
          (%i7) G10: map(lambda([x], power_mod(3, zn_log(x,2,5), 10)), G5);
          (%o7)                          [1, 3, 7, 9]

     Wird <gcd> auf 'all' gesetzt, wird die Tabelle für sämtliche
     Elemente in (Z/<n>Z) ausgegeben.

     Das dritte Argument <max_exp> erlaubt, den höchsten Exponenten zu
     wählen.  Die folgende Tabelle zeigt ein kleines RSA-Beispiel.

          (%i1) N:2*5$ phi:totient(N)$ e:7$ d:inv_mod(e,phi)$

          (%i5) zn_power_table(N, all, e*d);
                 [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 ]
                 [                                                               ]
                 [ 1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1 ]
                 [                                                               ]
                 [ 2  4  8  6  2  4  8  6  2  4  8  6  2  4  8  6  2  4  8  6  2 ]
                 [                                                               ]
                 [ 3  9  7  1  3  9  7  1  3  9  7  1  3  9  7  1  3  9  7  1  3 ]
                 [                                                               ]
                 [ 4  6  4  6  4  6  4  6  4  6  4  6  4  6  4  6  4  6  4  6  4 ]
          (%o5)  [                                                               ]
                 [ 5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5 ]
                 [                                                               ]
                 [ 6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6 ]
                 [                                                               ]
                 [ 7  9  3  1  7  9  3  1  7  9  3  1  7  9  3  1  7  9  3  1  7 ]
                 [                                                               ]
                 [ 8  4  2  6  8  4  2  6  8  4  2  6  8  4  2  6  8  4  2  6  8 ]
                 [                                                               ]
                 [ 9  1  9  1  9  1  9  1  9  1  9  1  9  1  9  1  9  1  9  1  9 ]

 -- Funktion: zn_primroot (<n>)
 -- Funktion: zn_primroot (<n>, [[<p1>, <e1>], ..., [<pk>, <ek>]])

     Ist die multiplikative Gruppe (Z/<n>Z)* zyklisch, berechnet
     'zn_primroot' die kleinste Primitivwurzel modulo <n>.  Dies ist der
     Fall, wenn <n> gleich '2', '4', 'p^k' oder '2*p^k' ist, wobei 'p'
     ungerade und prim und 'k' eine natürliche Zahl ist.  'zn_primroot'
     führt einen entsprechenden Prätest durch, wenn die Optionsvariable
     'zn_primroot_pretest' (Standardwert: 'false') 'true' gesetzt wurde.
     In jedem Fall wird die Suche durch die obere Schranke
     'zn_primroot_limit' begrenzt.

     Ist (Z/<n>Z)* nicht zyklisch oder kann bis 'zn_primroot_limit'
     keine Primitivwurzel modulo <n> gefunden werden, gibt 'zn_primroot'
     'false' zurück.

     Der verwendete Algorithmus benötigt die Primfaktorzerlegung des
     Totienten von <n>.  Diese Berechnung kann zeitaufwändig sein und es
     kann daher eventuell sinnvoll sein, die Primfaktoren des Totienten
     vorab zu berechnen und 'zn_primroot' als zusätzliches Argument zu
     übergeben.  Die Form muss dabei der Rückgabe von
     'ifactors(totient(n))' mit der Standardeinstellung 'false' der
     Optionsvariable 'factors_only' entsprechen.

     Siehe auch 'zn_primroot_p', 'zn_order', 'ifactors', 'totient'.

     Beispiele:

     'zn_primroot' berechnet die kleinste Primitivwurzel modulo <n> oder
     gibt 'false' zurück.

          (%i1) n : 14$
          (%i2) g : zn_primroot(n);
          (%o2)                               3
          (%i3) zn_order(g, n) = totient(n);
          (%o3)                             6 = 6
          (%i4) n : 15$
          (%i5) zn_primroot(n);
          (%o5)                             false

     Das optionale zweite Argument muss der Rückgabe von
     'ifactors(totient(n))' entsprechen.

          (%i1) (p : 2^142 + 217, primep(p));
          (%o1)                             true
          (%i2) ifs : ifactors( totient(p) )$
          (%i3) g : zn_primroot(p, ifs);
          (%o3)                               3
          (%i4) [time(%o2), time(%o3)];
          (%o4)                    [[15.556972], [0.004]]
          (%i5) is(zn_order(g, p, ifs) = p - 1);
          (%o5)                             true
          (%i6) n : 2^142 + 216$
          (%i7) ifs : ifactors(totient(n))$
          (%i8) zn_primroot(n, ifs),
                zn_primroot_limit : 200, zn_primroot_verbose : true;
          `zn_primroot' stopped at zn_primroot_limit = 200
          (%o8)                             false

 -- Optionsvariable: zn_primroot_limit
     Standardwert: '1000'

     Definiert die obere Schranke für die Suche von 'zn_primroot' nach
     einer Primitivwurzel.  Wurde die Optionsvariable
     'zn_primroot_verbose' (Standardwert: 'false') 'true' gesetzt, wird
     beim Erreichen von 'zn_primroot_limit' ein entsprechender Hinweis
     ausgegeben.

 -- Funktion: zn_primroot_p (<x>, <n>)
 -- Funktion: zn_primroot_p (<x>, <n>, [[<p1>, <e1>], ..., [<pk>,
          <ek>]])

     Testet, ob <x> eine Primitivwurzel in der multiplikativen Gruppe
     (Z/<n>Z)* ist.

     Der verwendete Algorithmus benötigt die Primfaktorzerlegung des
     Totienten von <n>.  Wird dieser Test nacheinander auf mehrere
     Zahlen angewandt, kann es sinnvoll sein, die Primfaktoren des
     Totienten vorab zu berechnen und 'zn_primroot_p' als zusätzliches
     drittes Argument zu übergeben.  Die Form muss dabei der Rückgabe
     von 'ifactors(totient(n))' mit der Standardeinstellung 'false' der
     Optionsvariable 'factors_only' entsprechen.

     Siehe auch 'zn_primroot', 'zn_order', 'ifactors', 'totient'.

     Beispiele:

     'zn_primroot_p' als Prädikatfunktion.

          (%i1) n : 14$
          (%i2) units_14 : sublist(makelist(i,i,1,13), lambda([i], gcd(i, n) = 1));
          (%o2)                     [1, 3, 5, 9, 11, 13]
          (%i3) zn_primroot_p(13, n);
          (%o3)                            false
          (%i4) sublist(units_14, lambda([x], zn_primroot_p(x, n)));
          (%o4)                            [3, 5]
          (%i5) map(lambda([x], zn_order(x, n)), units_14);
          (%o5)                      [1, 6, 6, 3, 3, 2]

     Das optionale dritte Argument muss der Rückgabe von
     'ifactors(totient(n))' entsprechen.

          (%i1) (p : 2^142 + 217, primep(p));
          (%o1)                             true
          (%i2) ifs : ifactors( totient(p) )$
          (%i3) sublist(makelist(i,i,1,50), lambda([x], zn_primroot_p(x, p, ifs)));
          (%o3)      [3, 12, 13, 15, 21, 24, 26, 27, 29, 33, 38, 42, 48]
          (%i4) [time(%o2), time(%o3)];
          (%o4)                   [[7.748484], [0.036002]]

 -- Optionsvariable: zn_primroot_pretest
     Standardwert: 'false'

     Eine multiplikative Gruppe (Z/'n'Z)* ist zyklisch, wenn 'n' gleich
     '2', '4', 'p^k' oder '2*p^k' ist, wobei 'p' prim und größer '2' und
     'k' eine natürliche Zahl ist.

     'zn_primroot_pretest' entscheidet darüber, ob 'zn_primroot' vor der
     Berechnung der kleinsten Primitivwurzel in (Z/'n'Z)* überprüft, ob
     auf 'n' überhaupt einer der oben genannten Fälle zutrifft.  Nur
     wenn 'zn_primroot_pretest' 'true' ist, wird dieser Prätest
     ausgeführt.

 -- Optionsvariable: zn_primroot_verbose
     Standardwert: 'false'

     Entscheidet, ob 'zn_primroot' beim Erreichen von
     'zn_primroot_limit' einen Hinweis ausgibt.

