Tutorium
Tutorium
MuPAD® Tutorial
How to Contact MathWorks
www.mathworks.com                 Web
comp.soft-sys.matlab              Newsgroup
www.mathworks.com/contact_TS.html Technical Support
508-647-7000 (Phone)
508-647-7001 (Fax)
Trademarks
MuPAD is a registered trademark of SciFace Software GmbH & Co. KG. MATLAB and Simulink
are registered trademarks of The MathWorks, Inc. See www.mathworks.com/trademarks for a list
of additional trademarks. Other product or brand names may be trademarks or registered
trademarks of their respective holders.
Patents
MathWorks products are protected by one or more U.S. patents. Please see
www.mathworks.com/patents for more information.
                                                               Preface
This book explains the basic use of the MuPAD® computer algebra system, and
gives some insight into the power of the system. MuPAD is available as part of the
Symbolic Math Toolbox™ in MATLAB® .
The book does not include the information about the latest features available in
MuPAD. The updated documentation is available in the MuPAD Help Browser.
To open the Help Browser, start MuPAD and click the Open Help button on the
desktop toolbar or use the Help menu. Also see the Release Notes section in the
MuPAD Help Browser for the short summary of the new features, bug fixes, and
upgrade issues.
This introduction addresses mathematicians, engineers, computer scientists,
natural scientists and, more generally, all those in need of mathematical
computations for their education or their profession. Generally speaking, this
book addresses anybody who wants to use the power of a modern computer
algebra package.
There are two ways to use a computer algebra system. On the one hand, you may
use the mathematical knowledge it incorporates by calling system functions
interactively. For example, you can compute symbolic integrals or generate and
invert matrices by calling appropriate functions. They comprise the system’s
mathematical intelligence and may implement sophisticated algorithms.
Chapters 2 through 14 discuss this way of using the MuPAD engine.
On the other hand, with the help of the MuPAD programming language, you can
easily add functionality to the system by implementing your own algorithms as
MuPAD procedures. This is useful for special purpose applications if no
appropriate system functions exist. Chapters 15 through 17 are an introduction to
MuPAD programming.
You can read this book in the standard way “linearly” from the first to the last
page. However, there are reasons to proceed otherwise. This may be the case, e.g.,
if you are interested in a particular problem, or if you already know something
about MuPAD.
For beginners, we recommend to start reading Chapter 2, which gives a first
survey of MuPAD. The description of the online help system in Section 2.2 is
probably the most important part of this chapter. The help system provides
information about details of system functions, their syntax, their calling
Preface
      ii
                                                                                       Preface
                                                                                           iii
                                                                                                   Contents
                                                                                                                   Preface
i
                                                                                                   Introduction
1
    Numerical Computations . . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    1-2
    Computer Algebra . . . . . . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    1-3
    Characteristics of Computer Algebra Systems                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    1-5
    MuPAD® Software . . . . . . . . . . . . . . .                  .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    1-6
                                                                                         MuPAD® Objects
           4
               Operands: the Functions op and nops . .           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    4-3
               Numbers . . . . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    4-6
               Identifiers . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    4-8
               Symbolic Expressions . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-12
                     Operators . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-12
                     Expression Trees . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-19
                     Operands . . . . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-21
               Sequences . . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-24
               Lists . . . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-28
               Sets . . . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-36
               Tables . . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-40
               Arrays . . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-44
               Boolean Expressions . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-47
               Strings . . . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-49
               Functions . . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-52
               Series Expansions . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-56
               Algebraic Structures: Fields, Rings, etc. .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-60
               Vectors and Matrices . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-64
                     Definition of Matrices and Vectors          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-64
                     Computing with Matrices . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-70
                     Special Methods for Matrices . . .          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-72
                     The Libraries linalg and numeric            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-74
                     Sparse Matrices . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-77
                     An Application . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-78
               Polynomials . . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4-81
     vi
                                                                                                                       Contents
                                                                                                                            vii
Contents
                                                            Manipulating Expressions
            9
                 Transforming Expressions . . . . . . . . . . . . . . . . . . . . . . . . .                         9-3
                 Simplifying Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . .                     9-13
                 Assumptions about Mathematical Properties . . . . . . . . . . . . . . .                           9-19
                                                                                                  Graphics
            11
                 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .     11-1
                 Easy Plotting: Graphs of Functions . . . . . . . . . . . . .         .   .   .   .   .   .   .    11-2
                       2D Function Graphs . . . . . . . . . . . . . . . . . .         .   .   .   .   .   .   .    11-2
                       3D Function Graphs . . . . . . . . . . . . . . . . . .         .   .   .   .   .   .   .   11-18
                 Advanced Plotting: Principles and First Examples . . . . .           .   .   .   .   .   .   .   11-33
                       General Principles . . . . . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   11-33
                       Some Examples . . . . . . . . . . . . . . . . . . . . .        .   .   .   .   .   .   .   11-39
                 The Full Picture: Graphical Trees . . . . . . . . . . . . . .        .   .   .   .   .   .   .   11-46
                 Viewer, Browser, and Inspector: Interactive Manipulation             .   .   .   .   .   .   .   11-50
                 Primitives . . . . . . . . . . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   11-54
                 Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   11-57
                       Default Values . . . . . . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   11-57
                       Inheritance of Attributes . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   11-58
                       Primitives Requesting Scene Attributes: “Hints” . .            .   .   .   .   .   .   .   11-62
                       The Help Pages of Attributes . . . . . . . . . . . . . .       .   .   .   .   .   .   .   11-65
     viii
                                                                                                                             Contents
     Colors . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                   .   .   .   .   .   .   .   .     11-67
           RGB Colors . . . . . . . . . . . . . . . . . . . . . .                       .   .   .   .   .   .   .   .     11-67
           HSV Colors . . . . . . . . . . . . . . . . . . . . . .                       .   .   .   .   .   .   .   .     11-69
     Animations . . . . . . . . . . . . . . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .      11-71
           Generating Simple Animations . . . . . . . . . . .                           .   .   .   .   .   .   .   .      11-71
           Playing Animations . . . . . . . . . . . . . . . . . .                       .   .   .   .   .   .   .   .     11-75
           The Number of Frames and the Time Range . . . .                              .   .   .   .   .   .   .   .     11-76
           What Can Be Animated? . . . . . . . . . . . . . . .                          .   .   .   .   .   .   .   .     11-78
           Advanced Animations: The Synchronization Model                               .   .   .   .   .   .   .   .     11-79
           Frame by Frame Animations . . . . . . . . . . . . .                          .   .   .   .   .   .   .   .     11-83
           Examples . . . . . . . . . . . . . . . . . . . . . . .                       .   .   .   .   .   .   .   .     11-90
     Groups of Primitives . . . . . . . . . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .     11-95
     Transformations . . . . . . . . . . . . . . . . . . . . . . .                      .   .   .   .   .   .   .   .     11-97
     Legends . . . . . . . . . . . . . . . . . . . . . . . . . . . .                    .   .   .   .   .   .   .   .   11-100
     Fonts . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                    .   .   .   .   .   .   .   .   11-104
     Saving and Exporting Pictures . . . . . . . . . . . . . . .                        .   .   .   .   .   .   .   .   11-107
           Interactive Saving and Exporting . . . . . . . . . .                         .   .   .   .   .   .   .   .   11-107
           Batch Mode . . . . . . . . . . . . . . . . . . . . . .                       .   .   .   .   .   .   .   .   11-108
     Importing Pictures . . . . . . . . . . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .   11-110
     Cameras in 3D . . . . . . . . . . . . . . . . . . . . . . . .                      .   .   .   .   .   .   .   .    11-112
     Strange Effects in 3D? Accelerated OpenGL® library? . .                            .   .   .   .   .   .   .   .   11-120
                                                                                                                                   ix
Contents
                                                                                                                            Utilities
           13
                User-Defined Preferences . . . . . . . . . . . .                .   .   .   .   .   .   .   .   .   .   .   .   .   . 13-2
                The History Mechanism . . . . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   .   . 13-6
                Information on MuPAD® Algorithms . . . . .                      .   .   .   .   .   .   .   .   .   .   .   .   .   . 13-9
                Restarting a MuPAD® Session . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   .   . 13-11
                Executing Commands of the Operating System                      .   .   .   .   .   .   .   .   .   .   .   .   .   . 13-12
                                                                                                    Type Specifiers
           14
                The Functions type and testtype . . . . . . . . . . . . . . . . . . . . .                                               14-2
                Comfortable Type Checking: the Type Library . . . . . . . . . . . . . .                                                 14-4
                                                                                                                                Loops
           15
                                                                                MuPAD® Procedures
           17
                Defining Procedures . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   17-3
                The Return Value of a Procedure . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   17-5
                Returning Symbolic Function Calls .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   17-7
                Local and Global Variables . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   17-9
     x
                                                                                                                 Contents
    Subprocedures . . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   17-14
    Scope of Variables . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .    17-17
    Type Declaration . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   17-20
    Procedures with a Variable Number of Arguments           .   .   .   .   .   .   .   .   .   .   .   .   17-21
    Options: the Remember Table . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   17-23
    Input Parameters . . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   17-27
    Evaluation Within Procedures . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   17-29
    Function Environments . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   17-31
    A Programming Example: Differentiation . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   17-38
    Programming Exercises . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   17-41
                                                    Solutions to Exercises
A
                                                                 Graphics Gallery
C
                                                                                                                       xi
Contents
                   Index
           Index
     xii
                                                                  1
Introduction
    Numerical Computations
                   Many a mathematical problem can be solved approximately by numerical
                   computations. The computation steps operate on numbers, which are stored
                   internally in floating-point representation. This representation has the drawback
                   that neither computations nor solutions are exact due to rounding errors. In
                   general, numerical algorithms find approximate solutions as fast as possible.
                   Often such solutions are the only way to handle a mathematical problem
                   computationally, in particular if there is no “closed form” solution known. (The
                   most popular example for this situation are roots of polynomials of high degrees.)
                   Moreover, approximate solutions are useful if exact results are unnecessary (e.g.,
                   in visualization).
    1-2
                                                                                              Computer Algebra
Computer Algebra
             In contrast to numerical computations, there are symbolic computations in
             computer algebra. [Hec 93] defines them as “computations with symbols
             representing mathematical objects.” Here, an object may be a number, but also a
             polynomial, an equation, an expression or a formula, a function, a group, a ring,
             or any other mathematical object. Symbolic computations with numbers are
             carried out exactly. Internally, numbers are represented as quotients of integers
             of arbitrary length (limited by the amount of storage available, of course). These
             kinds of computations are called symbolic or algebraic. [Hec 93] gives the
             following definitions:
                                                                                                           1-3
1   Introduction
    1-4
                                                                    Characteristics of Computer Algebra Systems
1 The MuPAD programming language is structured similarly to Pascal, with extensions such as lan-
                                                                                                                     1-5
1   Introduction
    MuPAD® Software
                   In comparison to other computer algebra systems, MuPAD® has the following
                   noteworthy features, which are not discussed in detail in this book:
                   The heart of the MuPAD engine is its kernel, which is implemented in C++. It
                   comprises the following main components:
                      – The parser reads the input to the system and performs a syntax check. If no
                        errors are found, it converts the input to a MuPAD data type.
                      – The evaluator processes and simplifies the input. Its mode of operation is
                        discussed later.
                      – Some frequently used algorithms such as, e.g., arithmetical functions are
                        implemented as kernel functions in C.
                   Parser and evaluator define the MuPAD language as described in this book. The
                   MuPAD libraries, which contain most of the mathematical knowledge of the
                   system, are implemented in this language.
                   In addition, MuPAD offers comfortable user interfaces for generating notebooks
                   or graphics, or to debug programs written in the MuPAD language. The MuPAD
                   help system has hypertext functionality. You can navigate within documents and
                   execute examples by a mouse click.
                   Symbolic Math Toolbox™ also offers a way of using the MuPAD engine to solve
                   problems directly from the MATLAB® environment, using either commands as
    1-6
                                                                       MuPAD® Software
presented here or, for a selected subset of commands, alternatives fitting more
closely into a MATLAB language program. This book does not discuss these
options, but limits itself to using the MuPAD engine directly, along with the
MuPAD GUIs.
                                                                                   1-7
                                                                      2
      Computer algebra systems such as MuPAD® are often used interactively. For
      example, you can enter an instruction to multiply two numbers and have MuPAD
      compute the result and print it on the screen.
      The following section will give a short description of the user interface. The next
      one after that describes the help system. Requesting a help page is probably the
      most frequently used command for the beginner. The section after that is about
      using MuPAD as an “intelligent pocket calculator”: calculating with numbers.
      This is the easiest and the most intuitive part of this tutorial. Afterwards we
      introduce some system functions for symbolic computations. The corresponding
      section is written quite informally and gives a first insight into the symbolic
      features of the system.
2   First Steps in MuPAD®
    Notebook interface
                            After you call the MuPAD® program, you will see the welcome dialog. From there,
                            you can enter the help system (which is, of course, also available later and will be
                            described on page 2-4), open an existing file, create a new MuPAD source file or
                            open a new notebook. Usually, you will wish to open an existing or a new
                            notebook.
                            After starting the program, you can enter commands in the MuPAD language.
                            These commands should be typed into “input regions,” which look like this:
                            If you press the <Return> key, this finishes your input and MuPAD evaluates the
                            command that you have entered. Holding <Shift> while pressing <Return>
                            provokes a linefeed, which you can use to format your input.
                            After invoking the command, you will see its result printed in the same bracket,
                            below the input, and if you were at the end of the notebook, a new input region
                            will be opened below:
                             sin(3.141)
                                0.0005926535551
                            The system evaluated the usual sine function at the point 3.141 and returned a
                            floating-point approximation of the value, similar to the output of a pocket
                            calculator.
                            You can at any time go back to older inputs and edit them. Also, you can click
                            between the brackets and add text. Editing output is not possible, but you can
                            copy formulas from the output and paste them someplace else. (When copying a
                            formula to an input region, it will be automatically translated into an equivalent
                            command in textual form.)
                            If you terminate your command with a colon, then MuPAD executes the command
                            without printing its result on the screen. This enables you to suppress the output
                            of irrelevant intermediate results.
    2-2
                                                                         Notebook interface
You can enter more than one command in one line. Two subsequent commands
have to be separated by a semicolon or a colon, if the result of the first command
is to be printed or not, respectively:
 diff(sin(x^2), x); int(%, x)
            ( )
     2 x cos x2
        ( )
     sin x2
Here x^2 denotes the square of x, and the MuPAD functions diff and int
perform the operations “differentiate” and “integrate” (Chapter 7). The character
% returns the previous expression (in the example, this is the derivative of sin(x2 )).
The concept underlying % is discussed in Chapter 13.2.
In the following example, the output of the first command is suppressed by the
colon, and only the result of the second command appears on the screen:
 equations := {x + y = 1, x - y = 1}:
 solve(equations)
     {[x = 1, y = 0]}
                                                                                          2-3
2   First Steps in MuPAD®
?solve
                            The help system is a hypertext system, i.e., similar to browsing the web. Active
                            keywords are underlined. If you click on them, you obtain further information
                            about the corresponding notion. The tooltips mentioned above also work in the
                            help system. You can edit and execute the examples in the help system or copy
                            and paste them to a notebook.
                            Exercise 2.1: Find out how to use the MuPAD differentiator diff, and compute
                            the fifth derivative of sin(x2 ).
    2-4
                                                                                                Computing with Numbers
            You see that the returns are exact results (and not rounded floating-point
            numbers) when computing with integers and rational numbers:
             (1 + (5/2*3))/(1/7 + 7/9)^2
                  67473
                  6728
1 In this printout, the “backslash” \ at the end of a line indicates that the result is continued on the
next line. To break long lines in this way, you need to switch off typesetting in the “Notebook” menu.
                                                                                                                           2-5
2   First Steps in MuPAD®
                            The function isprime checks whether a positive integer is prime. It returns either
                            TRUE or FALSE.
                             isprime(123456789)
                                 FALSE
                            Exact Computations
                                                                                   √
                            Now suppose that we want to “compute” the number 56. The problem is that the
                            value of this irrational number cannot be expressed as a quotient
                            numerator/denominator of two integers exactly. Thus “computation” can only
                            mean √to find an exact representation that is as simple as possible. When you
                            input 56 via sqrt, MuPAD returns the following:
                             sqrt(56)
                                  √
                                 2 14
                                                                √                        √                  √
                            The result of the simplification of 56 is the exact value 2 · 14. In MuPAD, 14
                            (or, sometimes, 14^(1/2)) represents the positive solution of the equation
                            x2 = 14. Indeed,
                                       √      this is probably the most simple representation of the result. We
                            stress that 14 is a genuine object with certain properties (e.g., that its square can
                            be simplified to 14). The system applies them automatically when computing with
                            such objects. For example:
                             sqrt(14)^4
                                 196
    2-6
                                                                Computing with Numbers
To enter this number in MuPAD, you have to use E or exp(1), where exp
represents the exponential function. MuPAD knows exact rules of manipulation
for this object. For example, using the natural logarithm ln we find:
 ln(1/exp(1))
    −1
Numerical Approximations
The precision of the approximation depends on the value of the global variable
DIGITS, which determines the number of decimal digits for numerical
computations. Its default value is 10:
 DIGITS; float(67473/6728)
    10
10.02868609
                                                                                   2-7
2   First Steps in MuPAD®
                            Global variables such as DIGITS affect the behavior of MuPAD, and are also called
                            environment variables.2 You find a complete list of all environment variables in
                            Section “Environment Variables” of the MuPAD Quick Reference in the online
                            documentation. The variable DIGITS can assume any integral value between 1 and
                            232 − 1, although 1000 can already be considered very large and it is unlikely that
                            using more than 10 000 digits is reasonable for anything but the most unusual
                            calculations:
                             DIGITS := 100: float(67473/6728); DIGITS := 10:
                                10.02868608799048751486325802615933412604042806183115\
                                338882282996432818073721759809750297265160523187
                            We have reset the value of DIGITS to 10 for the following computations. This can
                            also be achieved via the command delete DIGITS. For arithmetic operations with
                            numbers, MuPAD automatically uses approximate computation as soon as at
                            least one of the numbers involved is a floating-point value:
                             (1.0 + (5/2*3))/(1/7 + 7/9)^2
                                 10.02868609
                            (The separation of both values by a comma generates a special data type, namely a
                            sequence, which is described in Section 4.5.)
2 You should be particularly cautious when the same computation is performed with different values
                            of DIGITS. Some of the more intricate numerical algorithms in MuPAD employ the option “remember.”
                            This implies that they store previously computed values to be used again (Section 17.9), which can lead
                            to inaccurate numerical results if the remembered values were computed with lower precision. To be
                            safe, you should restart the MuPAD session using reset() before increasing the value of DIGITS. This
                            command clears memory and resets all environment variables to their default values (Section 13.4).
    2-8
                                                                                Computing with Numbers
The constants π and e are denoted by PI and E = exp(1), respectively. MuPAD can
perform exact computations with them:
 cos(PI), ln(E)
      −1, 1
    2.718281828459045235360287471352662497757247093699959\
    574966967627724076630353547594571382178525166427
                         √        √
Exercise 2.2: Compute 27 − 2 3 and cos(π/8) exactly. Determine numerical
approximations to a precision of 5 digits.
Complex Numbers
                     √
The imaginary unit −1 is represented in MuPAD by the symbol I in the input
and an upright i in the typeset output:
3 Take a look at the last digits. The second command yields a slightly less accurate result, since
0.666 . . . is already an approximation of 2/3 and the rounding error is propagated to the final result.
                                                                                                           2-9
2   First Steps in MuPAD®
                             sqrt(-1), I^2
                                i, −1
                            You can input complex numbers in the usual mathematical notation x + y i. Both
                            the real part x and the imaginary part y may be integers, rational numbers, or
                            floating-point numbers:
                             (1 + 2*I)*(4 + I), (1/2 + I)*(0.1 + I/2)^3
                                2 + 9 i, 0.073 − 0.129 i
                            If you use symbolic expressions such as, e.g., sqrt(2), MuPAD may not return the
                            result of a calculation in Cartesian coordinates:
                             1/(sqrt(2) + I)
                                     1
                                 √
                                     2+i
                            The function rectform (short for: rectangular form) ensures that the result is split
                            into its real and imaginary parts:
                             rectform(1/(sqrt(2) + I))
                                 √
                                   2   i
                                     −
                                  3    3
                            The functions Re and Im return the real part x and the imaginary part y ,
                            respectively, of a complex number x + y i. The functions conjugate, abs
                                                                                                 √ , and arg
                            compute the complex conjugate x − y i, the absolute value |x + y i| = x2 + y 2 ,
                            and the polar angle, respectively:
                             Re(1/(sqrt(2) + I)), Im(1/(sqrt(2) + I)),
                             conjugate(1/(sqrt(2) + I)),
                             abs(1/(sqrt(2) + I)), arg(1/(sqrt(2) + I)),
                             rectform(conjugate(1/(sqrt(2) + I)))
                                 √               √              (√ ) √
                                   2    1    1     3              2    2   i
                                     , − , √   ,     , − arctan     ,    +
                                  3     3   2−i 3                2    3    3
    2-10
                                                                                                 Symbolic Computation
Symbolic Computation
             This section comprises some examples of MuPAD® sessions that illustrate a small
             selection of the system’s power for symbolic manipulation. The mathematical
             knowledge is contained essentially in the MuPAD functions for differentiation,
             integration, simplification of expressions etc. This demonstration does not
             proceed in a particularly systematic manner: we apply the system functions to
             objects of various types, such as sequences, sets, lists, expressions etc. They are
             explained in detail one by one in Chapter 4.
Introductory Examples
             Here, we have computed both the derivative with respect to x and to y . You may
             obtain higher derivatives either by nested calls of diff, or by a single call:
              diff(diff(diff(f, x), x), x) = diff(f, x, x, x)
                   24 x + 24 = 24 x + 24
4 Internally, symbolic sums are ordered according to certain rules that enable the system to access
             the terms faster. Of course, such a reordering of the input happens only for commutative operations such
             as, e.g., addition or multiplication, where changing the order of the operands yields a mathematically
             equivalent object.
                                                                                                                        2-11
2   First Steps in MuPAD®
                            Alternatively, you can use the differential operator ', which maps a function to its
                            derivative:
                             sin', sin'(x)
                                 cos, cos(x)
                            The symbol ' for the derivative is a short form of the differential operator D. The
                            call D(function) returns the derivative:
                             D(sin), D(sin)(x)
                                 cos, cos(x)
                            Note: MuPAD uses a mathematically strict notation for the differential operator: D
                            (or, equivalently, the ' operator) differentiates functions, while diff differentiates
                            expressions. In the example, the ' maps the (name of the) function to the (name
                            of the) function representing the derivative. You often find a sloppy notation such
                            as, e.g., (x + x2 )′ for the derivative of the function F : x 7→ x + x2 . This notation
                            confuses the map F and the image point f = F (x) at a point x. MuPAD has a
                            strict distinction between the function F and the expression f = F (x), which are
                            realized as different data types. The map corresponding to f can be defined by
                             F := x -> x + x^2:
                            Then
                             diff(F(x), x) = F'(x)
                                 2x + 1 = 2x + 1
                            You can compute integrals by using int. The following command computes a
                            definite integral on the real interval between 0 and 1:
                             int(f, x = 0..1)
                                        26
                                 y2 +
                                        5
    2-12
                                                                    Symbolic Computation
Note that int returns a special antiderivative, not a general one (with additive
constant).
If you try to compute the indefinite integral of an expression and it cannot be
represented by elementary functions, then int returns the call symbolically:
 integral := int(1/(exp(x^2) + 1), x)
    ∫
               1
                    dx
            ex2 + 1
                                                                                   2-13
2   First Steps in MuPAD®
                            root sqrt, the exponential function exp, the trigonometric functions sin, cos, tan,
                            the hyperbolic functions sinh, cosh, tanh, the corresponding inverse functions ln,
                            arcsin, arccos, arctan, arcsinh, arccosh, arctanh, as well as a variety of other
                            special functions such as, e.g., the gamma function, the error function erf, Bessel
                            functions (besselI, besselJ, …), etc. (Section “Special Mathematical Functions”
                            of the MuPAD Quick Reference gives a survey.) In particular, MuPAD knows the
                            rules of manipulation for these functions (e.g., the addition theorems for the
                            trigonometric functions) and applies them. It can compute floating-point
                            approximations such as, e.g., float(exp(1)) = 2.718..., and knows special
                            values (e.g., sin(PI) = 0).
                            If you call these functions, they often return themselves symbolically, since this is
                            the most simple exact representation of the corresponding value:
                             sqrt(2), exp(1), sin(x + y)
                                √
                                 2, e, sin(x + y)
                            For many users, the main feature of the system is to simplify or transform such
                            expressions using the rules for computation. For example, the system function
                            expand “expands” functions such as exp, sin, etc. by means of the addition
                            theorems if their argument is a symbolic sum:
                             expand(exp(x + y)), expand(sin(x + y)),
                             expand(tan(x + 3*PI/2))
                                                                               1
                                ex ey , cos(x) sin(y) + cos(y) sin(x) , −
                                                                            tan(x)
    2-14
                                                                  Symbolic Computation
The functions simplify and Simplify are universal simplifiers and try to find a
representation that is as “simple” as possible:
 simplify((exp(x) - 1)/(exp(x/2) + 1))
      x
    e2 − 1
             3                          (x − z) · (x + z)
    (x + 1) , (x + y − 2) · (x + y) ,
                                            (x + y)
                                                                                  2-15
2   First Steps in MuPAD®
                            The function limit does what its name suggests. For example, the function
                            sin(x)/x has a removable pole at x = 0. Its limit for x → 0 is 1:
                             limit(sin(x)/x, x = 0)
                                1
                            In a MuPAD session, you can define functions of your own in several ways. A
                            simple and intuitive method is to use the arrow operator -> (the minus symbol
                            followed by the “greater than” symbol):
                             F := x -> (x^2):      F(x), F(y), F(a + b), F'(x)
                                    2   2      2
                                x , y , (a + b) , 2 x
    2-16
                                                                   Symbolic Computation
Here, we have generated a set of two equations and a set of unknowns which we
wish to solve for. solve returns the result in terms of simplified equations, from
which you can read off the solution. In the above example, there are two more
symbolic parameters a and b. This is why we have told solve which of the symbols
it should express in terms of the others. The “option” IgnoreSpecialCases tells
MuPAD to ignore the possibility that a could be −1, where the above solution
would be incorrect. Without this option, MuPAD returns a complete solution with
three branches:
                                                                                     2-17
2   First Steps in MuPAD®
                             solve(equations, unknowns)
                                  {[                     ]}
                                 
                                     x = a2 +b
                                                , y = a−b
                                                             if a ̸= −1
                                         a+1         a+1
                                   {[x = −z − 1, y = z]} if a = −1 ∧ b = −1
                                 
                                 
                                               ∅             if a = −1 ∧ b ̸= −1
                            In the following example, we have only one equation in one unknown. MuPAD
                            automatically recognizes the unknown and solves for it:
                             solve(x^2 - 2*x + 2 = 0)
                                 {[x = 1 − i] , [x = 1 + i]}
                            If we supply the unknown x to solve for, the format of the output changes:
                             solve(x^2 - 2*x + 2 = 0, x)
                                 {1 − i, 1 + i}
                            The result is a set containing the two (complex) solutions of the quadratic
                            equation. You find a detailed description of solve in Chapter 8.
                            The functions sum and product handle symbolic sums and products. For example,
                            the well-known sum 1 + 2 + · · · + n is:
                             sum(i, i = 1..n)
                                 n (n + 1)
                                     2
n!3
    2-18
                                                                             Symbolic Computation
There exist several data structures for vectors and matrices. In principle, you may
use arrays (Section 4.9) to represent such objects. However, it is far more intuitive
to work with the data type “matrix.” You can generate matrices by using the
system function matrix:
 A := matrix([[1, 2], [a, 4]])
    (           )
        1 2
        a 4
Matrix objects constructed this way have the convenient property that the basic
arithmetic operations +, *, etc. are specialized (“overloaded”) according to the
appropriate mathematical context. For example, you may use + or * to add or
multiply matrices, respectively (if the dimensions match):
 B := matrix([[y, 3], [z, 5]]):
 A, B, A + B, A*B
    (           ) (                 ) (           ) (                        )
        1 2                y 3            y+1 5         y + 2z      13
                    ,                ,             ,
        a 4                z 5            a+z 9         4 z + a y 3 a + 20
The power A^(-1), equivalent to 1/A, denotes the inverse of the matrix:
 A^(-1)
    (                               )
        − a−2
           2
                          a−2
                             1
            a
        2 (a−2)         − 2 (a−2)
                              1
The function linalg::det, from the MuPAD linalg library for linear algebra
(Section 4.15), computes the determinant:
 linalg::det(A)
    4 − 2a
                                                                                            2-19
2   First Steps in MuPAD®
                            You can comfortably determine the solution A−1⃗b of the system of linear
                            equations A⃗x = ⃗b, with the above coefficient matrix A and the previously defined ⃗b
                            on the right-hand side:
                             solutionVector := A^(-1)*b
                                (                            )
                                           x
                                         a−2   −     2
                                                   a−2
                                         a
                                     2 (a−2)   −       x
                                                   2 (a−2)
                            Now you can apply the function normal to each component of the vector by means
                            of the system function map, thus simplifying the representation:
                             map(%, normal)
                                (            )
                                      x−2
                                      a−2
                                      a−x
                                     2 a−4
                            To verify the computation, you may multiply the solution vector by the matrix A:
                             A * %
                                (                            )
                                       x−2   2 (a−x)
                                       a−2 + 2 a−4
                                     4 (a−x)   a (x−2)
                                      2 a−4 + a−2
                                                                        x2 − 1
                            Exercise 2.4: Use MuPAD to check that              = x − 1 holds.
                                                                        x+1
    2-20
                                                                                 Symbolic Computation
Exercise 2.6: Obtain detailed information about the function limit. Use
MuPAD to verify the following limits:
               sin(x)         1 − cos(x)
         lim          = 1,        lim      = 0,                lim ln(x) = −∞ ,
        x→0       x                x
                                 x→0                          x→0+
                               (     1 )x                          ln(x)
        lim xsin(x) = 1 ,  lim 1 +         = e,                lim        = 0,
        x→0               x→∞        x                        x→∞    ex
                               (     π ) x                              2
         lim xln(x) = ∞ , lim 1 +          = eπ ,              lim             = 0.
        x→0+              x→∞        x                        x→0− 1 + e−1/x
The limit lim ecot(x) does not exist. How does MuPAD react?
         x→0
Exercise 2.7: Obtain detailed information about the function sum. The call
sum(f(k), k = a..b) computes a closed form of a finite or infinite sum, if possible.
Use MuPAD to verify the following identity:
                          ∑
                          n
                                                  n (n2 + 3 n + 5)
                                (k 2 + k + 1) =                    .
                                                         3
                          k=1
Curve Sketching
In the following sample session, we use some of the system functions from the
previous section to sketch and discuss the curve given by the rational function
                                              (x − 1)2
                                   f : x 7→            +a
                                               x−2
                                                                                                2-21
2   First Steps in MuPAD®
                            Depending on a, either both or none of the two roots are real. Now, we want to
                            find the local extrema of f . To this end, we determine the roots of the first
                            derivative f ′ :
                             f'(x)
                                                   2
                                 2 x − 2 (x − 1)
                                        −
                                  x−2     (x − 2)
                                                 2
                             extrema := solve(f'(x) = 0, x)
                                {1, 3}
                            These are the candidates for local extrema. However, some of them might be
                            saddle points. If the second derivative f ′′ does not vanish at these points, then
                            both are really extrema. We check:
    2-22
                                                                    Symbolic Computation
 f''(1), f''(3)
    −2, 2
Our results imply that f has the following properties: for any choice of the
parameter a, there is a local maximum at x = 1, a pole at x = 2, and a local
minimum at x = 3. The corresponding values of f at these points are
 maxvalue := f(1); minvalue := f(3)
    a
a+4
                                                                                      2-23
2   First Steps in MuPAD®
plot(F, G, H, x = -1..4)
                            These routines are quite fast. However, since they employ probabilistic primality
                            tests, they may return wrong results with very small probability.5 Instead of
                            isprime, you can use the (slower) function numlib::proveprime as an error-free
                            primality test.
5 In practice, you need not worry about this because the chances of a wrong answer are negligible:
                            the probability of a hardware failure is much higher than the probability that the randomized test returns
                            the wrong answer on correctly working hardware.
    2-24
                                                                     Symbolic Computation
Let us generate a list of all primes up to 10 000. Here is one of many ways to do
this:
 primes := select([$ 1..10000], isprime)
        [2, 3, 5, 7, 11, 13, 17, ..., 9949, 9967, 9973]
Here we have used the fact that we already know the number of primes up to
10 000. Another possibility is to generate a large list of primes and discard the
ones greater than 10 000:
 primes := select([ithprime(i) $ i=1..5000],
                  x -> (x<=10000)):
Here, the object x -> (x <= 10000) represents the function that maps each x to the
inequality x <= 10000. The select command then keeps only those list elements
for which the inequality evaluates to TRUE.
In the next example, we use a repeat loop (Chapter 15) to generate the list of
primes. With the help of the concatenation operator . (Section 4.6), we
successively append primes i to a list until nextprime(i+1), the next prime greater
than i, exceeds 10 000. We start with the empty list and the first prime i = 2:
 primes := []: i := 2:
 repeat
   primes := primes . [i];
   i := nextprime(i + 1)
 until i > 10000 end_repeat:
                                                                                      2-25
2   First Steps in MuPAD®
                            We want to verify this conjecture for all even numbers up to 10 000. First, we
                            generate the list of even integers [4, 6, …, 10000]:
                             list := [2*i $ i = 2..5000]:
                             nops(list)
                                 4999
                            Now, we select those numbers from the list that cannot be written in the form
                            “prime + 2.” This is done by testing for each i in the list whether i − 2 is a prime:
                             list := select(list, i -> (not isprime(i - 2))):
                             nops(list)
                                 4998
                            The only integer that has been eliminated is 4 (since for all other even positive
                            integers i − 2 is even and greater than 2, and hence not prime). Now we discard all
                            numbers of the form “prime + 3”:
                             list := select(list, i -> (not isprime(i - 3))):
                             nops(list)
                                 3770
                            The remaining 3770 integers are neither of the form “prime + 2” nor of the form
                            “prime + 3.” We now continue this procedure by means of a while loop
                            (Chapter 15). In the loop, j successively runs through all primes > 3, and the
                            numbers of the form “prime + j ” are eliminated. A print command (Section 12.1)
                            outputs the number of remaining integers in each step. The loop ends as soon as
                            the list is empty:
                             j := 3:
    2-26
                                                                  Symbolic Computation
7, 1926
11, 1400
...
163, 1
167, 1
173, 0
Thus we have confirmed that Goldbach’s conjecture holds true for all even
positive integers up to 10 000. We have even shown that all those numbers can be
written as a sum of a prime less or equal to 173 and another prime.
In the next example, we generate a list of distances between two successive primes
up to 500:
 primes := select([$ 1..500], isprime):
 distances := [primes[i] - primes[i - 1]
               $ i = 2..nops(primes)]
   [1, 2, 2, 4, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2,
6, 4, 2, 6, 4, 6, 8, 4, 2, 4, 2, 4, 14, 4, 6, 2,
2, 10, 2, 6, 4, 6, 8, 4, 2, 4, 12, 8, 4, 8]
The indexed call primes[i] returns the ith element in the list.
                                                                                     2-27
2   First Steps in MuPAD®
                            The function zip (Section 4.6) provides an alternative method. The call
                            zip(a, b, f) combines two lists a = [a1 , a2 , . . . ] and b = [b1 , b2 , . . . ]
                            componentwise by means of the function f : the resulting list is
[f (a1 , b1 ), f (a2 , b2 ), . . . ]
                            and has as many elements as the shorter of the two lists. In our example, we apply
                            this to the prime list a = [a1 , . . . , an ], the “shifted” prime list b = [a2 , . . . , an ], and
                            the function (x, y) 7→ y − x. We first generate a shifted copy of the prime list by
                            deleting the first element, thus shortening the list:
                             b := primes: delete b[1]:
                            We have presented another useful function in Section 2.3, the routine ifactor for
                            factoring an integer into primes. The call ifactor(n) returns an object of the
                            same type as factor: it is a special data type called Factored. Objects of this type
                            are printed on the screen in a form that is easily readable:
                             ifactor(-123456789)
                                 −32 · 3607 · 3803
                            Internally, the prime factors and the exponents are stored in form of a list, and
                            you can extract them by using op or by an indexed access. Consult the help pages
                            of ifactor and Factored for details. The internal list has the format
[s, p1 , e1 , . . . , pk , ek ]
                            with primes p1 , . . . , pk , their exponents e1 , . . . , ek , and the sign s = ±1, such that
                            n = s · pe11 · pe22 · · · pekk :
                             op(%)
                                 −1, 3, 2, 3607, 1, 3803, 1
    2-28
                                                                               Symbolic Computation
We now employ the function ifactor to find out how many integers between 2
and 10 000 are divisible by exactly two distinct prime numbers. We note that the
object returned by ifactor(n) has 2 m + 1 elements in its list representation,
where m is the number of distinct prime divisors of n. Thus, the function
 m := n -> (nops(ifactor(n)) - 1)/2:
returns the number of distinct prime factors. We construct the list of values m(k)
for k = 2, . . . , 10000:
 list := [m(k) $ k = 2..10000]:
The following for loop (Section 15) displays the number of integers with precisely
i = 1, 2, . . . , 6 distinct prime divisors:
 for i from 1 to 6 do
     print(i, nops(select(list, x -> (x = i))))
 end_for:
       1, 1280
2, 4097
3, 3695
4, 894
5, 33
6, 0
Thus there are 1280 integers with exactly one prime divisor in the scanned
interval,6 4097 integers with precisely two distinct prime factors, and so on. It is
easy to see why the interval contains no integer with six or more prime divisors:
the smallest such number 2 · 3 · 5 · 7 · 11 · 13 = 30 030 exceeds 10 000.
The numlib library comprises various number theoretic functions. Among others,
it contains the routine numlib::numprimedivisors, equivalent to the above m, for
computing the number of prime divisors. We refer to Chapter 3 for a description
of the MuPAD libraries.
6 We have already seen that the interval contains 1229 prime numbers. Can you explain the dif-
ference?
                                                                                                     2-29
2   First Steps in MuPAD®
    2-30
                                                                     3
                             -- Interface:
                             numlib::Lambda,                     numlib::Omega,
                             numlib::contfrac,                   numlib::cornacchia,
                             numlib::decimal,                    numlib::divisors,
                             numlib::ecm,                        numlib::factorGaussInt,
                             numlib::fibonacci,                  numlib::fromAscii,
                             ...
                       As for other system functions, you will see information when hovering your mouse
                       pointer over the name of a library function and you may request information on
                       the function by means of help or ?:
                           ?numlib::decimal
    3-2
                                                   Information About a Particular Library
You can have a look at the implementation of a library function by using expose:
 expose(numlib::decimal)
   proc(a)
     name numlib::decimal;
     local p, q, s, l, i;
   begin
     if not testtype(a, Type::Numeric) then
         ...
   end_proc
                                                                                     3-3
3   The MuPAD® Libraries
    Exporting Libraries
                       In the previous section, you have seen that the calling syntax for a library function
                       is library::function, where library and function are the names of the library
                       and the function, respectively. For example, the library numeric for numerical
                       computations contains the function numeric::fsolve. It implements a modified
                       version of the well-known Newton method for numerical root finding. In the
                       following example, we approximate a root of the sine function in the interval [2, 4]:
                           numeric::fsolve(sin(x), x = 2..4)
                             [x = 3.141592654]
                       The function use2 makes functions of a library “globally known,” so that you can
                       use them without specifying the library name:
                           use(numeric, fsolve): fsolve(sin(x), x = 2..4)
                             [x = 3.141592654]
                       If you already have assigned a value to the name of the function to be exported,
                       use returns a warning and the function is not exported. In the following, the
                       numerical integrator numeric::quadrature cannot be exported to the name
                       quadrature, because this identifier has a value:
                       After deletion of the value, the name of the function is available and the
                       corresponding library function can be exported successfully. One can export
                       several functions at once:
                           delete quadrature:
                           use(numeric, realroots, quadrature):
                       Now you can use realroots (to find all real roots of an expression in an interval)
                       and quadrature (for numerical integration) directly. Please refer to the
                       corresponding help pages for the meaning of the input parameters and the
                       returned output. Please note that neither tooltips nor the help command will
                          2 This function used to be called export, but that name is more appropriately used for the library
    3-4
                                                                        Exporting Libraries
react to exported names. You will need to use the full name (or the search
functionality of the help browser) in these cases.
 realroots(x^4 + x^3 - 6*x^2 + 11*x - 6,
           x = -10..10, 0.001)
    [[−3.623046875, −3.62109375] , [0.8217773438, 0.822265625]]
 quadrature(exp(x) + 1, x = 0..1)
    2.718281828
If you call use with only one argument, namely the name of the library, then all
functions in that library are exported. If there are name conflicts with already
existing identifiers, then use issues warnings:
 eigenvalues := 1: use(numeric)
   Info: 'numeric::quadrature' already is exported.
   Info: 'numeric::realroots' already is exported.
   Warning: 'indets' already has a value, not exported.
   Info: 'numeric::fsolve' already is exported.
   Warning: 'rationalize' already has a value, not
            exported.
   Warning: 'linsolve' already has a value, not exported.
   Warning: 'sum' already has a value, not exported.
   Warning: 'int' already has a value, not exported.
   Warning: 'solve' already has a value, not exported.
   Warning: 'sort' already has a value, not exported.
   Warning: 'eigenvalues' already has a value, not
            exported.
After deleting the value of the identifier eigenvalues, the library function with the
same name can be exported successfully:
 delete eigenvalues: use(numeric, eigenvalues):
However, the other name conflicts int, solve etc. cannot be resolved. The
important symbolic system functions int, solve etc. should not be replaced by
their numerical counterparts numeric::int, numeric::solve etc.
                                                                                        3-5
3   The MuPAD® Libraries
    3-6
                                                                      4
MuPAD® Objects
                                                                                                     
                      domain type           meaning
                      DOM_TABLE             tables
                      DOM_BOOL              Boolean values: TRUE, FALSE, UNKNOWN
                      DOM_STRING            strings, e.g., "I am a string"
                      Dom::Matrix(R)        matrices and vectors over the ring R
                      DOM_POLY              polynomials, e.g., poly(x^2 + x + 1, [x])
                      DOM_PROC              functions and procedures
                                                                                                     
                     Moreover, you can define your own data types, but we do not discuss this here.
                     The system function domtype returns the domain type of a MuPAD object.
                     In the following section, we first present the important operand function op,
                     which enables you to decompose a MuPAD object into its building blocks. The
                     following sections discuss the above data types and some of the main system
                     functions for handling them.
    4-2
                                                                  Operands: the Functions op and nops
             The meaning of an operand depends on the data type of the object. We discuss this
             for each data type in detail in the following sections. For example, the operands of
             a rational number are the numerator and the denominator, the operands of a list
             or set are the elements, and the operands of a function call are the arguments.
             However, there are also objects where the decomposition into operands is less
             intuitive, such as series expansions as generated by the system functions taylor
             or series (Section 4.13). Here is an example with a list (Section 4.6):
              list := [a, b, c, d, sin(x)]: nops(list)
                 5
              op(list, 2)
                 b
              op(list, 3..5)
                 c, d, sin(x)
              op(list)
                 a, b, c, d, sin(x)
                                                                                                    4-3
4   MuPAD® Objects
                     that cannot be further decomposed by op, such that op(atom) = atom holds.1 This
                     is essentially the case for integers, floating-point numbers, identifiers that have
                     not been assigned a value, and for strings:
                      op(-2), op(0.1234), op(a), op("I am a text")
                           −2, 0.1234, a, ”I am a text”
                     In the following example, a nested list is decomposed completely into its atoms
                     a11, a12, a21, x, 2:
1 This model is a good approximation to MuPAD’s internal mode of operation, but there are some
                     exceptions. For example, you can decompose rational numbers via op, but the kernel regards them as
                     atoms. On the other hand, although strings are indecomposable with respect to op, it is still possible to
                     access the characters of a string individually (Section 4.11).
    4-4
                                                         Operands: the Functions op and nops
Instead of the annoying nested calls of op, you may also use the following short
form to access subexpressions:
                                                                    
                      op(list, [1])                :   [a11, a12]
                      op(list, [2])                :   [a21, x^2]
                      op(list,    [1,     1])      :   a11
                      op(list,    [1,     2])      :   a12
                      op(list,    [2,     1])      :   a21
                      op(list,    [2,     2])      :   x^2
                      op(list,    [2,     2, 1])   :   x
                      op(list,    [2,     2, 2])   :   2
                                                                    
Exercise 4.1: Determine the operands of the power a^b, the equation a = b, and
the symbolic function call f(a, b).
Extract the value of the solution for y and assign it to the identifier y.
                                                                                        4-5
4   MuPAD® Objects
    Numbers
                     We have demonstrated in Section 2.3 how to work with numbers. There are
                     various data types for numbers:
                      domtype(-10), domtype(2/3), domtype(0.1234),
                      domtype(0.1 + 2*I)
                         DOM_INT, DOM_RAT, DOM_FLOAT, DOM_COMPLEX
                     A rational number is a compound object: the building blocks are the numerator
                     and the denominator. Similarly, a complex number consists of the real and the
                     imaginary part. You can use the operand function op from the previous section to
                     access these components:
                      op(111/223, 1), op(111/223, 2)
                         111, 223
                      op(100 + 200*I, 1), op(100 + 200*I, 2)
                         100, 200
                     Alternatively, you can use the system functions numer, denom, Re, and Im:
                      numer(111/223), denom(111/223),
                      Re(100 + 200*I), Im(100 + 200*I)
                         111, 223, 100, 200
                     Besides the common arithmetic operations +, -, *, and /, there are the arithmetic
                     operators div and mod for division of an integer x by a non-zero integer p with
                     remainder. If x = k p + r holds with integers k and 0 ≤ r < |p|, then x div p
                     returns the “integral quotient” k and x mod p returns the “remainder” r:
                      25 div 4, 25 mod 4
                         6, 1
                     Table 4.2 gives a compilation of the main MuPAD functions and operators for
                     handling numbers. We refer to the help system (i.e., ?abs, ?ceil etc.) for a
                     detailed
                     √        description of these functions. We stress that while expressions such as
                       2 mathematically represent numbers, MuPAD treats them as symbolic
                     expressions (Section 4.4):
    4-6
                                                                                   Numbers
                                                                          
           +, -, *, /, ^ : basic arithmetic operations
           abs           : absolute value
           ceil          : rounding up
           div           : quotient “modulo”
           fact          : factorial
           float           :   approximation by floating-point numbers
           floor           :   rounding down
           frac            :   fractional part
           ifactor, factor :   prime factorization
           isprime         :   primality test
           mod             :   remainder “modulo”
           round           :   rounding to nearest
           sign              : sign
           sqrt              : square root
           trunc             : integral part
                                                                          
                                ®
             Table 4.2: MuPAD functions and operators for numbers
 domtype(sqrt(2))
    DOM_EXPR
Exercise 4.3: What is the difference between 1/3 + 1/3 + 1/3 and
1.0/3 + 1/3 + 1/3 in MuPAD?
                                                         π       1
                                                                     √
Exercise 4.4: Compute the decimal expansions of π (π ) and e 3 π 163 with a
precision of 10 and 100 digits, respectively. What is the 234-th digit after the
decimal point of π ?
Exercise 4.5: After you execute x:= 10^50/3.0, only the first DIGITS decimal
digits of x are guaranteed to be correct.
                                                                                       4-7
4   MuPAD® Objects
    Identifiers
                     Identifiers are names such as x or f that may represent variables and unknowns.
                     They may consist of arbitrary combinations of letters, digits, the hash mark “#,”
                     and the underscore “_,” with the only exception that the first symbol must not be a
                     digit. Identifiers starting with a hash mark can never have values or properties.
                     MuPAD® distinguishes uppercase and lowercase letters. Examples of admissible
                     identifiers are x, _x23, and the_MuPAD_system, while MuPAD would not accept
                     12x, p-2, and x>y as identifiers. MuPAD also accepts any sequence of characters
                     starting and ending with a ‘backtick’ ` as an identifier, so `x>y` is, in fact, an
                     identifier. We will not use such identifiers in this tutorial.
                     Identifiers that have not been assigned a value evaluate to their name. In MuPAD,
                     they represent symbolic objects such as unknowns in equations. Their domain
                     type is DOM_IDENT:
                      domtype(x)
                         DOM_IDENT
                     the identifier x has the value 1 + I, which is a complex number of domain type
                     DOM_COMPLEX. You should be careful to distinguish between an identifier, its value,
                     and its evaluation. We refer to the important Chapter 5, where MuPAD’s
                     evaluation strategy is described.
                     If an identifier already has been assigned a value, another assignment overwrites
                     the previous value. The statement y:= x does not assign the identifier x to the
                     identifier y, but the current value (the evaluation) of x:
    4-8
                                                                                    Identifiers
 x := 1: y := x: x, y
     1, 1
2, 2
Here we have deleted the value of the identifier x by means of the function delete.
After deletion, x is again a symbolic identifier without a value.
The assignment operator := is a short form of the system function _assign, which
may also be called directly:
 _assign(x, value): x
     value
This function returns its second argument, namely the right-hand side of an
assignment. This explains the screen output after an assignment:
 y := 2*x
     2 value
You can work with the returned value immediately. For example, the following
construction is allowed (the assignment must be put in parentheses):
 y := cos((x := 0)): x, y
     0, 1
Here the value 0 is assigned to the identifier x. The return value of the assignment,
i.e., 0, is fed directly as argument to the cosine function, and the result cos(0) = 1
is assigned to y. Thus, we have simultaneously assigned values to both x and y.
                                                                                          4-9
4   MuPAD® Objects
                     Another assignment function is assign. Its input are sets or lists of equations,
                     which are transformed into assignments:
                      delete x, y: assign({x = 0, y = 1}): x, y
                         0, 1
                     This function is particularly useful in connection with solve (Section 8), which
                     returns solutions as a set containing lists of equations of the form
                     identifier = value without assigning these values.
                     There exist many identifiers with predefined values. They represent mathematical
                     functions (such as sin, exp, or sqrt), mathematical constants (such as PI), or
                     MuPAD algorithms (such as diff, int, or limit). If you try to change the value of
                     such a predefined identifier, MuPAD issues a warning or an error message:
                      sin := 1
                        Error: Identifier 'sin' is protected [_assign]
                     You can protect your own identifiers against overwriting via the command
                     protect(identifier). The write protection of both your own and of system
                     identifiers can be removed by unprotect(identifier). However, we strongly
                     recommend not to overwrite predefined identifiers, since they are used by many
                     system functions which would return unpredictable results after a redefinition.
                     Identifiers starting with a hash mark (#) are always protected and cannot be
                     unprotected. The command anames(All) lists all currently defined identifiers.
                     You can use the concatenation operator “.” to generate names of identifiers
                     dynamically. If x and i are identifiers, then x.i generates a new identifier by
                     concatenating the evaluations (see Chapter 5) of x and i:
                      x := z: i := 2:      x.i
                         z2
                      x.i := value: z2
                         value
                     In the following example, we use a for loop (Chapter 15) to assign values to the
                     identifiers x1, ..., x1000:
                      delete x:
                      for i from 1 to 1000 do x.i := i^2 end_for:
    4-10
                                                                                       Identifiers
You may use strings enclosed in quotation marks " (Section 4.11) to generate
identifiers dynamically:
 a := email: b := "4you": a.b
     email4you
Exercise 4.6: Which of the following names x, x2, 2x, x_t, diff, exp,
caution!-!, x-y, Jack&Jill, a_valid_identifier, #1 are valid identifiers?Which
of them can be assigned values?
Exercise 4.7: Read the help page for solve. Solve the system of equations
in the unknowns x1 , x2 , . . . , x20 . Read the help page for assign and assign the
values of the solution to the unknowns.
                                                                                            4-11
4   MuPAD® Objects
    Symbolic Expressions
                     We say that an object containing symbolic terms such as the equation
                                                                           f (x, y)
                                                        0.3 + sin(3) +              =0
                                                                              5
                     is an expression. Expressions of domain type DOM_EXPR are probably the most
                     general data type in MuPAD® . Expressions are built of atomic components, as all
                     MuPAD objects, and are composed by means of operators. This comprises binary
                     operators, such as the basic arithmetic operations +, -, *, /, ^, and function calls
                     such as sin(·), f(·), etc.
Operators
                     You may input these operators in the familiar mathematical way, but internally
                     they are function calls:
2 Remarkably, the MuPAD kernel treats not only genuine function calls, such as sin(0.2), assign-
                     ments, or arithmetical operations in a functional way, but also loops (Chapter 15) and case distinctions
                     (Chapter 16).
                         3 LISP   programmers may disagree.
    4-12
                                                                                        Symbolic Expressions
The same holds for the factorial of a nonnegative integer. You may input it in the
mathematical notation n!. Internally it is converted to a call of the function fact:
 n! = fact(n), fact(10)
      n! = n!, 3628800
The arithmetic operators div and mod4 were presented in Chapter 4.2. They may
also be used in a symbolic context, but then return only symbolic results:
 x div 4, 25 mod p
      x div 4, 25 mod p
x, x2 , x3 , x4 , x5
Equations and inequalities are valid MuPAD objects. They are generated by the
equality sign = and by <>, respectively:
 equation := x + y = 2; inequality := x <> y
      x+y =2
x ̸= y
4 The object x mod p is converted to the function call _mod(x, p). The function _mod can be redefined,
e.g., _mod:= modp or _mod:= mods. The behavior of modp and mods is documented on the corresponding
help pages. A redefinition of _mod also redefines the operator mod.
                                                                                                              4-13
4   MuPAD® Objects
                     The operators <, <=, >, and >= compare the magnitudes of their arguments. The
                     corresponding expressions represent conditions:
                      condition := i <= 2
                         i≤2
                     In a concrete context, they usually can be evaluated to one of the truth (“Boolean”)
                     values TRUE or FALSE. Typically, they are used in if statements or as termination
                     conditions in loops. You may combine Boolean expressions via the logical
                     operators and and or, or negate them via not:
                      condition3 := condition1 and (not condition2)
                         condition1 ∧ ¬condition2
                     You can define maps (functions) in several ways in MuPAD. The simplest method
                     is to use the arrow operator -> (the minus symbol followed by the “greater than”
                     symbol):
                      f := x -> x^2
                         x → x2
                     After defining a function in this way, you may call it like a system function:
                      f(4), f(x + 1), f(y)
                                       2
                         16, (x + 1) , y 2
                     If you wish to define a function that first treats the right-hand side as a command
                     to be performed, use the double arrow operator -->:
                      g1 := x -> int(f(x), x);
                      g2 := x --> int(f(x), x)
                               ∫
                         x→         f (x) dx
                               x3
                         x→
                               3
    4-14
                                                                     Symbolic Expressions
Some system functions, such as definite integration via int or the $ operator,
require a range. You generate a range by means of the operator ..:
 range := 0..1;     int(x, x = range)
    0..1
     1
     2
Table 4.3 lists all operators presented above together with their equivalent
functional form. You may use either form to input expressions:
 2/14 = _divide(2, 14);
     1   1
       =
     7   7
                                                                                    4-15
4   MuPAD® Objects
                                                                                             
                                      system
                           operator   function    meaning       example
                              +       _plus  addition           SUM:= a + b
                              -       _subtract
                                             subtraction        Difference:= a - b
                              *       _mult  multiplication     Product:= a * b
                              /       _dividedivision           Quotient:= a/b
                              ^       _power exponentiation     Power:= a^b
                             div      _div   quotient           Quotient:= a div p
                                              modulo p
                            mod   _mod       remainder          Remainder:= a mod p
                                              modulo p
                              !   fact       factorial          n!
                              $   _seqgen    sequence           Sequence:= i^2 $ i = 3..5
                                              generation
                              ,   _exprseq   sequence           Seq:= Seq1, Seq2
                                              concatenation
                           union  _union     set union          S:= Set1 union Set2
                        intersect _intersect set intersection   S:= Set1 intersect Set2
                           minus  _minus     set difference     S:= Set1 minus Set2
                              =   _equal     equation           Equation:= x+y = 2
                             <>   _unequal   inequality         Condition:= x <> y
                              <   _less      comparison         Condition:= a < b
                              >              comparison         Condition:= a > b
                             <=   _leequal   comparison         Condition:= a <= b
                             >=              comparison         Condition:= a >= b
                            not   _not       negation           Condition2:= not Condition1
                            and   _and       logical ‘and’      Condition:= a < b and b < c
                             or   _or        logical ‘or’       Condition:= a < b or b < c
                             ->              mapping            Square:= x -> x^2
                              '   D          differential       f'(x)
                                             operator
                              @   _fconcat   composition        h:= f @ g
                             @@   _fnest     iteration          g:= f @@ 3
                              .   _concat    concatenation      NewName:= Name1.Name2
                             ..   _range     range              Range:= a..b
                            ...   interval   interval           IV:= 2.1 ... 3.5
                          name()             function call      sin(1), f(x), reset()
                                                                                             
    4-16
                                                                      Symbolic Expressions
We remark that some of the system functions such as _plus, _mult, _union, or
_concat accept arbitrarily many arguments, while the corresponding operators
are only binary:
 _plus(a, b, u, v), _concat(a, b, u, v), _union()
    a + b + u + v, abuv, ∅
It is often useful to know and to use the functional form of the operators. For
example, it is very efficient to form longer sums by applying _plus to many
arguments. You may generate the argument sequence quickly by means of the
sequence generator $:
 _plus(1/i! $ i = 0..100): float(%)
    2.718281828
The function map is a useful tool. It applies a function to all operands of a MuPAD
object. For example:
 map([x1, x2, x3], function, y, z)
    [function(x1, y, z) , function(x2, y, z) , function(x3, y, z)]
If you want to apply operators via map, use their functional equivalent:
 map([x1, x2, x3], _power, 5), map([f, g], _fnest, 5)
    [ 5            ]
     x1 , x25 , x35 , [f ◦ f ◦ f ◦ f ◦ f, g ◦ g ◦ g ◦ g ◦ g]
For the most common operators, namely +, -, *, /, ^, =, <>, <, >, <=, >=, ==>, and
<=>, the corresponding functions can be accessed in the form `+`, `-`, `*` etc.:
                                                                                      4-17
4   MuPAD® Objects
                     The system function _and recognizes that the argument 3 cannot represent a
                     Boolean value and issues an error message. However, MuPAD accepts a symbolic
                     expression such as a and b with symbolic identifiers a, b. As soon as a and b get
                     Boolean values, the expression can be evaluated to a Boolean value as well:
                      c := a and b: a := TRUE: b := TRUE: c
                         TRUE
                     You find a complete list of the operators and their priorities in Section “Operators”
                     of the MuPAD Quick Reference. Parentheses can always be used to enforce an
                     evaluation order that differs from the standard priority of the operators:
                      1 + 1 mod 2,        1 + (1 mod 2)
                         0, 2
    4-18
                                                                               Symbolic Expressions
 i := 2: x.i^2, x.(i^2)
     x22 , x4
 u, v $ 3; (u, v) $ 3
     u, v, v, v
u, v, u, v, u, v
Expression Trees
a * *
                              b         c
                                                d            e         ^
sin g
                                                                  f
int(exp(x^4), x = 0..1)
int
exp =
^ x ..
x 4 0 1
                                                                                              4-19
4   MuPAD® Objects
a *
b -1
a ^
b -1
                     Exercise 4.9: Determine the operands of 2/3, x/3, 1 + 2*I, and x + 2*I. Explain
                     the differences that you observe.
    4-20
                                                                        Symbolic Expressions
Operands
If the expression is a symbolic function call, op(·, 0) returns the identifier of that
function:
 op(sin(1), 0), op(f(x), 0), op(diff(y(x), x), 0)
     sin, f, diff
You may regard the 0th operand of an expression as a “mathematical type.” For
example, an algorithm for differentiation of arbitrary expressions must find out
whether the expression is a sum, a product, or a function call. To this end, it may
look at the 0th operand to decide whether linearity, the product rule, or the chain
rule of differentiation applies.
                                                                                         4-21
4   MuPAD® Objects
a b sin ^
x c 2
                     Note that the output order visible on the screen is different from the internal
                     order accessible by op. You can access the building blocks of an expression in
                     output order with the index operator [ ], as in the following:
                      expression[1], expression[4]
                         c2 , sin(x)
    4-22
                                                                     Symbolic Expressions
Exercise 4.10: Sketch the expression tree of the following Boolean expression:
 condition := (not a) and (b or c):
How can you use op to pick the symbolic identifiers a, b, and c out of the object
condition?
                                                                                    4-23
4   MuPAD® Objects
    Sequences
                     Sequences form an important MuPAD® data structure. Lists and sets are built
                     from sequences. As discussed in Section 4.4, a sequence is a series of MuPAD
                     objects separated by commas.
                      sequence1 := a, b, c; sequence2 := c, d, e
                         a, b, c
c, d, e
                     The operator $ is called the sequence generator. The equivalent functional form is
                     _seqgen(object(i), i, m..n)
                     Usually, you will prefer the operator notation. The functional form is useful in
                     connection with map, zip or similar functions.
                     You may use $ in the following way to generate a sequence of successive integers:
                      $ 23..30
                         23, 24, 25, 26, 27, 28, 29, 30
    4-24
                                                                               Sequences
You can also use the sequence generator in connection with the keyword in. (The
functional equivalent in this case in _seqin.) The loop variable then runs through
all operands of the stated object:
 f(x) $ x in [a, b, c, d]
    f (a) , f (b) , f (c) , f (d)
 f(x) $ x in a + b + c + d + sin(sqrt(2))
                                     ( (√ ))
    f (a) , f (b) , f (c) , f (d) , f sin 2
                 8            2            2     2
       23040 x           cos(x ) - 302400 x sin(x ) +
                     6        2           10      2
       161280 x          sin(x ) - 1024 x    sin(x )
                                                                                     4-25
4   MuPAD® Objects
                     The “void” object (Section 4.19) may be regarded as an empty sequence. You may
                     generate it by calling null() or _exprseq(). The system automatically eliminates
                     this object from sequences:
                      Seq := null(): Seq := Seq, a, b, null(), c
                           a, b, c
                     Some system functions such as the print command for screen output
                     (Section 12.1) return the null() object:
                      sequence := a, b, print(Hello), c
                        Hello
a, b, c
                     You can access the i-th entry of a sequence by sequence[i]. Redefinitions of the
                     form sequence[i]:= newvalue are also possible:
                      F := a, b, c: F[2]
                           b
                      F[2] := newvalue: F
                           a, newvalue, c
                     Alternatively, you may use the operand function op (Section 4.1) to access
                     subsequences:5
                      F := a, b, c, d, e: op(F, 2); op(F, 2..4)
                           b
b, c, d
5 Note that, in this example, the identifier F of the sequence is provided as argument to op. The op
                     function regards a direct call of the form op(a, b, c, d, e, 2) as an (invalid) call with six arguments and
                     issues an error message. You may use parentheses to avoid this error: op((a, b, c, d, e), 2).
    4-26
                                                                                       Sequences
You may use delete to delete entries from a sequence, thus shortening the
sequence:
 F; delete F[2]: F; delete F[3]: F
    a, b, c, d, e
a, c, d, e
a, c, e
The main usage of MuPAD sequences is the generation of lists and sets and
supplying arguments to function calls. For example, the functions max and min
can compute the maximum and minimum, respectively, of arbitrarily many
arguments:
 Seq := 1, 2, -1, 3, 0: max(Seq), min(Seq)
    3, −1
                                          ∑
                                          10 ∑
                                             i
                                                      1
                                                         .
                                          i=1 j=1
                                                     i+j
Hint: the function _plus accepts arbitrarily many arguments. Generate a suitable
argument sequence.
                                                                                           4-27
4   MuPAD® Objects
    Lists
                     A list is an ordered sequence of arbitrary MuPAD® objects enclosed in square
                     brackets:
                      list := [a, 5, sin(x)^2 + 4, [a, b, c], hello,
                               3/4, 3.9087]
                          [                                                        ]
                                          2                       3
                              a, 5, sin(x) + 4, [a, b, c] , hello, , 3.9087
                                                                  4
                     A list may occur on the left hand side of an assignment. This may be used to
                     assign values to several identifiers simultaneously:
                      [A, B, C] := [a, b, c]: A + B^C
                          a + bc
                     A useful property of this construction is that all the assignments are performed at
                     the same time, so you can swap values:
                      a := 1: b:= 2: a, b
                          1, 2
                      [a, b] := [b, a]: a, b
                          2, 1
    4-28
                                                                                       Lists
The function nops returns the number of elements of a list. You can access the
elements of a list by means of indexed access: list[i] returns the i-th list
element, and list[i..j] returns the sub-list starting at the i-th and extending up
to and including the j -th element. Negative values for i and j are counted from
the end:
 list := [a, b, c, d, e, f]: list[1], list[3..-2]
    2, [c, d, e]
As with almost any MuPAD object, you can also access the elements of a list with
the op function: op(list) returns the sequence of elements, i.e., the sequence
that has been used to construct the list by enclosing it in square brackets [ ]. The
call op(list, i) returns the i-th list element, and op(list, i..j) extracts the
sequence of the i-th up to the j -th list element:
 delete a, b, c: list := [a, b, sin(x), c]: op(list)
    a, b, sin(x) , c
 op(list, 2..3)
    b, sin(x)
                                                                                       4-29
4   MuPAD® Objects
1 a
                     You can remove elements from a list by using delete. This shortens the list:
                      list := [a, b, c]: delete list[1]: list
                          [b, c]
    4-30
                                                                                      Lists
A list can be sorted by means of the function sort. This arranges numerical values
according to their magnitude, strings (Section 4.11) are sorted lexicographically:
 sort([-1.23, 4, 3, 2, 1/2])
     [                   ]
               1
         −1.23, , 2, 3, 4
               2
Note that the lexicographical order only applies to strings generated with ".
Names of identifiers are sorted according to different (internal) rules, which only
reduce to lexicographic order for short identifiers (and may change in future
releases):
 delete A, B, C, a, b, c, a1, abc:
 sort([A, b, a, c, C, c, B, a1, abc])
     [A, B, C, a, a1, abc, b, c, c]
                                                                                      4-31
4   MuPAD® Objects
                     If the function has more than one argument, then map substitutes the list elements
                     for the first argument and takes the remaining arguments from its own argument
                     list:
                      map([a, b, c], f, y, z)
                          [f (a, y, z) , f (b, y, z) , f (c, y, z)]
                     This map construction is a powerful tool for handling lists as well as other MuPAD
                     objects. In the following example, we have a nested list L. We want to extract the
                     first elements of the sublists using op(·, 1). This is easily done using map:
                      L := [[a1, b1], [a2, b2], [a3, b3]]: map(L, op, 1)
                          [a1, a2, a3]
                     The MuPAD function select enables you to extract elements with a certain
                     property from a list. To this end, you need a function that checks whether an
                     object has this property and returns TRUE or FALSE. For example, the call
                     has(object1, object2) returns TRUE if object2 is an operand or suboperand of
                     object1, and FALSE otherwise:
                     Now,
                      select([a + 2, x, y, z, sin(a)], has, a)
                          [a + 2, sin(a)]
                     extracts all those list elements for which has(·,a) returns TRUE, i.e., those which
                     contain the identifier a.
                     The function split divides a list into three lists, as follows. The first list contains
                     all elements with a certain property, the second list collects all those elements
                     without the property. If the test for the property returns the value UNKNOWN for
                     some elements, then these are put into the third list. Otherwise, the third list is
                     empty:
                      split([sin(x), x^2, y, 11], has, x)
                          [[           ]              ]
                            sin(x) , x2 , [y, 11] , []
    4-32
                                                                                   Lists
The MuPAD function zip combines elements of two lists pairwise into a new list:
 L1 := [a, b, c]: L2 := [d, e, f]:
 zip(L1, L2, _plus), zip(L1, L2, _mult),
 zip(L1, L2, _power)
                                                 [            ]
     [a + d, b + e, c + f ] , [a d, b e, c f ] , ad , be , cf
The third argument of zip must be a function that takes two arguments. This
function is then applied to the pairs of list elements. In the above example, we
have used the MuPAD functions _plus, _mult, and _power for addition,
multiplication, and exponentiation, respectively. If the two input lists have
different lengths, then the behavior of zip depends on the optional fourth
argument. If this is not present, then the length of the resulting list is the
minimum of the lengths of the two input lists. Otherwise, if you supply an
additional fourth argument, then zip replaces the “missing” list entries by this
argument:
 L1 := [a, b, c, 1, 2]: L2 := [d, e, f]:
 zip(L1, L2, _plus)
     [a + d, b + e, c + f ]
Table 4.4 gives a summary of all list operations that we have discussed.
Exercise 4.15: Multiply all entries of the list [1, x, 2] by 2. Suppose you are
given a list, whose elements are lists of numbers or expressions, such as
[[1, x, 2], [PI], [2/3, 1]], how can you multiply all entries by 2?
                                                                                   4-33
4   MuPAD® Objects
                                                                                                                          
                                    . or _concat                  :   concatenating lists
                                    append                        :   appending elements
                                    contains(list, x)             :   does list contain the element x?
                                    list[i]                       :   accessing the i-th element
                                    map                           :   applying a function
                                    nops                          :   length
                                    op                            :   accessing elements
                                    select                        :   select according to properties
                                    sort                          :   sorting
                                    split                         :   split according to properties
                                    subsop                        :   replacing elements
                                    delete                        :   deleting elements
                                    zip                           :   combining two lists
                                                                                                                          
                                      Table 4.4: MuPAD® functions and operators for lists
                     Exercise 4.16: Let X = [x1 , . . . , xn ] and Y = [y1 , . . . , yn ] be two lists of the same
                     length. Find a simple method to compute
x1 y1 + · · · + xn yn ,
                                          [ [x1 y1 , x1 y2 , . . . , x1 yn ], [x2 y1 , x2 y2 , . . . , x2 yn ],
                                                                             . . . , [xn y1 , xn y2 , . . . , xn yn ]] .
                     You can achieve this by using zip, _plus, map and appropriate functions
                     (Section 4.12) within a single command line in each case. Loops (Chapter 15) are
                     not required.
                     Exercise 4.17: In number theory, one is often interested in the density of prime
                     numbers in sequences of the form f (1), f (2), . . . , where f is a polynomial. For
                     each value of m = 0, 1, . . . , 41, find out how many of the integers n2 + n + m with
                     n = 1, 2, . . . , 100 are primes.
    4-34
                                                                                  Lists
                                                                                  4-35
4   MuPAD® Objects
    Sets
                     A set is an unordered sequence of arbitrary objects enclosed in curly braces. Sets
                     are of domain type DOM_SET:
                      {34, 1, 89, x, -9, 8}
                         {−9, 1, 8, 34, 89, x}
                     The order of the elements in a MuPAD® list seems to be random. The MuPAD
                     kernel sorts the elements according to internal principles. You should use sets
                     only if the order of the elements does not matter. If you want to process a sequence
                     of expressions in a certain order, use lists as discussed in the previous section.
                     Sets may be empty:
                      emptyset := {}
                         ∅
                     A set contains each element only once, i.e., duplicate elements are removed
                     automatically:
                      set := {a, 1, 2, 3, 4, a, b, 1, 2, a}
                         {1, 2, 3, 4, a, b}
                     The function nops determines the number of elements in a set. As for sequences
                     and lists, op extracts elements from a set:
                      op(set)
                         a, 1, 2, 3, 4, b
                      op(set, 2..4)
                         1, 2, 3
                     Warning: Since elements of a set may be reordered internally, you should check
                     carefully whether it makes sense to access the i-th element. For example,
                     subsop(set, i = newvalue) (Section 6) replaces the i-th element by a new value.
                     However, you should check in advance (using op) that the element that you want
                     to replace really is the i-th element. Especially note that replacing an element of a
                     set often reorders other entries.
    4-36
                                                                                                         Sets
The command op(set, i) returns the i-th element of set in the internal order,
which usually is different from the i-th element of set that you see on the screen.
However, you can access elements by using set[i], where the returned elements
is the i-th element as printed on the screen.
The functions union, intersect, and minus form the union, the intersection, and
the set-theoretic difference, respectively, of sets:
 M1 := {1, 2, 3, a, b}: M2 := {a, b, c, 4, 5}:
 M1 union M2, M1 intersect M2, M1 minus M2, M2 minus M1
     {1, 2, 3, 4, 5, a, b, c} , {a, b} , {1, 2, 3} , {4, 5, c}
You can also replace an element by a new value without caring about the order of
the elements:
 set := {a, b, oldvalue, c, d}
     {a, b, c, d, oldvalue}
The function contains checks whether an element belongs to a set, and returns
either TRUE or FALSE:6
 contains({a, b, c}, a), contains({a, b, c + d}, c)
     TRUE, FALSE
6 Note the difference to the behavior of contains for lists: there the ordering of the elements is
determined when you generate the list, and contains returns the position of the element in the list.
                                                                                                         4-37
4   MuPAD® Objects
                                                                                                  
                                       contains(M, x)         :   does M contain the element x?
                                       intersect              :   intersection
                                       map                    :   applying a function
                                       minus                  :   set-theoretic difference
                                       nops                   :   number of elements
                                       op                     :   accessing elements
                                       select                 :   select according to properties
                                       split                  :   split according to properties
                                       subsop                 :   replacing elements
                                       union                  :   set-theoretic union
                                                                                                  
                                     Table 4.5: MuPAD® functions and operators for sets
                     You can use the function select to extract elements with a certain property from
                     a set. This works as for lists, but the returned object is a set:
                      select({{a, x, b}, {a}, {x, 1}}, contains, x)
                         {{1, x} , {a, b, x}}
                     Similarly, you can use the function split to divide a set into three subsets of
                     elements with a certain property, elements without that property, and elements
                     for which the system cannot decide this and returns UNKNOWN. The result is a list
                     comprising these three sets:
                      split({{a, x, b}, {a}, {x, 1}}, contains, x)
                         [{{1, x} , {a, b, x}} , {{a}} , ∅]
Exercise 4.19: How can you convert a list to a set and vice versa?
    4-38
                                                                                      Sets
Exercise 4.20: Generate the sets A = {a, b, c}, B = {b, c, d}, and C = {b, c, e}.
Compute the union and the intersection of the three sets, as well as the difference
A \ (B ∪ C).
Exercise 4.21: Instead of the binary operators intersect and union, you can
also use the corresponding MuPAD functions _intersect and _union to compute
unions and intersections of sets. These functions accept arbitrarily many
arguments. Use simple commands to compute the union and the intersection of
all sets belonging to M:
 M := {{2, 3}, {3, 4}, {3, 7}, {5, 3}, {1, 2, 3, 4}}:
                                                                                      4-39
4   MuPAD® Objects
    Tables
                     A table is a MuPAD® object of domain type DOM_TABLE. It is a collection of
                     equations of the form index = value. Both indices and values may be arbitrary
                     MuPAD objects. You can generate a table by using the system function table
                     (“explicit generation”):
                      T := table(a = b, c = d)
                           a b
                           c d
                     You can generate more entries or change existing ones by “indexed assignments”
                     of the form Table[index]:= value:
                      T[f(x)] := sin(x): T[1, 2] := 5:
                      T[1, 2, 3] := {a, b, c}: T[a] := B:
                      T
                                 a B
                                c d
                            f (x) sin(x)
                             1, 2 5
                           1, 2, 3 {a, b, c}
                     It is not necessary to initialize a table via table. If T is an identifier that does not
                     have a value, or has a value which does not allow indexed access (such as an
                     integer or a function), then an indexed assignment of the form T[index]:= value
                     automatically turns T into a table (“implicit generation”):
                      delete T: T[a] := b: T[b] := c: T
                           a b
                           b c
    4-40
                                                                                         Tables
d ac
You can access table entries in the form Table[index]; this returns the element
corresponding to the index. If there is no entry for the index, then MuPAD returns
Table[index] symbolically:
 T := table(a = b, c = d, d = a*c):
 T[a], T[b], T[c], T[d]
     b, Tb , d, a c
The call op(Table) returns all entries of a table, i.e., the sequence of all equations
index = value:
 op(table(a = A, b = B, c = C, d = D))
     a = A, b = B, c = C, d = D
Note that the internal order of the table entries may differ both from the order in
which you have generated the table and from the order of entries printed on the
screen. It may look quite random:
 op(table(a.i = i^2 $ i = 1..17))
   a16 = 256, a9 = 81, a12 = 144, a6 = 36, a3 = 9,
a13 = 169, a1 = 1
                                                                                          4-41
4   MuPAD® Objects
                     The function map applies a given function to the values (not the indices) of all
                     table entries:
                      T := table(1 = PI, 2 = 4, 3 = exp(1)): map(T, float)
                          1 3.141592654
                          2 4.0
                          3 2.718281828
                     You may employ the functions select and split to inspect both indices and
                     values of a table and to extract them according to certain properties. This works
                     similarly as for lists (Section 4.6) and for sets (Section 4.7):
                      T := table(1 = "number", 1.0 = "number", x = "symbol"):
                      select(T, has, "symbol")
x ”symbol”
1.0 ”number”
                     Tables are particularly well suited for storing large amounts of data. Indexed
                     accesses to individual elements are implemented efficiently also for big tables:
                     a write or read does not file through the whole data structure.
    4-42
                                                                                      Tables
Look up Ford’s number. How can you find out whose number is 5678?
Exercise 4.23: Given a table, how can you generate a list of all indices and a list
of all values, respectively?
                                                                                       4-43
4   MuPAD® Objects
    Arrays
                     Arrays, of domain type DOM_ARRAY, may be regarded as special tables. You may
                     think of them as a collection of equations of the form index = value, but in
                     contrast to tables, the indices must be integers. A one-dimensional array consists
                     of equations of the form i = value. Mathematically, it represents a vector whose
                     i-th component is value. A two-dimensional array represents a matrix, whose
                     (i, j)-th component is stored in the form (i, j) = value. You may generate arrays
                     of arbitrary dimension, with entries of the form (i, j, k, …) = value.
                     The system function array generates arrays. In its simplest form, you only specify
                     a sequence of ranges that determine the dimension and the size of the array:
                      A := array(0..1, 1..3)
                         (                   )
                             NIL NIL NIL
                             NIL NIL NIL
                     You can see here that the first range 0..1 and the second range 1..3 determine
                     the array’s number of rows and columns, respectively. The output ?[0, 1] signals
                     that the corresponding index has not been assigned a value, yet. Thus, the above
                     command has generated an empty array. Now, you can assign values to the
                     indices:
                      A[0, 1] := 1: A[0, 2] := 2: A[0, 3] := 3:
                      A[1, 3] := HELLO: A
                         (                       )
                              1   2    3
                             NIL NIL HELLO
                     You can also initialize the complete array directly when generating it by array.
                     Just supply the values as a (nested) list:
                      A := array(1..2, 1..3, [[1, 2, 3], [4, 5, 6]])
                         (           )
                             1 2 3
                             4 5 6
You can access and modify array elements in the same way as table elements:
    4-44
                                                                                                    Arrays
The internal structure of arrays differs from the structure of tables. The entries
are not stored in the form of equations:
 op(Mat)
     a, b, c, d, e, f
                                                                                                     4-45
4   MuPAD® Objects
                     The table type is more flexible than the array type: tables admit arbitrary indices,
                     and their size may grow dynamically. Arrays are intended for storing vectors and
                     matrices of a fixed size. When you enter an indexed call, the system checks
                     whether the indices are within the specified ranges. For example:
                      Mat[4, 7]
                        Error: Illegal argument [array]
                     You may apply a function to all array components via map. For example, here is
                     the simplest way to convert all array entries to floating-point numbers:
                      A := array(1..2, [PI, 1/7]): map(A, float)
                         (                               )
                             3.141592654 0.1428571429
M[1, 1] := a: M
1, 1 a
                     Additionally, MuPAD provides the more powerful data structures of domain type
                     Dom::Matrix for handling vectors and matrices. These are discussed in
                     Section 4.15. Such objects are very convenient to use: you can multiply two
                     matrices or a matrix and a vector by means of the usual multiplication symbol *.
                     Similarly, you can add matrices of equal dimension via +. To achieve the same
                     functionality with arrays, you have to write your own procedures. We refer to the
                     examples MatrixProduct and MatrixMult in Sections 17.4 and 17.5, respectively.
    4-46
                                                                                    Boolean Expressions
Boolean Expressions
             MuPAD® implements three logical (“Boolean”) values: TRUE, FALSE, and UNKNOWN:
              domtype(TRUE), domtype(FALSE), domtype(UNKNOWN)
                 DOM_BOOL, DOM_BOOL, DOM_BOOL
             The functions corresponding to these operators are _and, _or, and _not,
             respectively.
             The function bool evaluates equations, inequalities, or comparisons via >, >=, < ,
             <=, to TRUE or FALSE:
             Note that bool can only compare real numbers sufficiently distinct from one
             another. Especially exact symbolic representations of the same number cannot be
             compared with bool:
              bool(3 <= PI)
                 TRUE
              bool(sqrt(2)*sqrt(3) <= sqrt(6))
                Error: Can't evaluate to boolean [_leequal]
              bool(14885392687/4738167652 <= PI)
                Error: Can't evaluate to boolean [_leequal]
                                                                                                     4-47
4   MuPAD® Objects
                      i := 0:
                      repeat
                        i := i + 1;
                        if isprime(i)
                           then print(i, "is a prime")
                           else print(i, "is no prime")
                        end_if
                      until i = 3 end_repeat
                           1, "is no prime"
2, "is a prime"
3, "is a prime"
                     Here we have used strings enclosed in " for the screen output. They are discussed
                     in detail in Section 4.11. Note that it is not necessary to use the function bool in
                     branching or termination conditions in order to evaluate the condition to TRUE or
                     FALSE.
                     Exercise 4.26: Let ∧ denote the logical “and,” let ∨ denote the logical “or,” let ¬
                     denote logical negation. To which Boolean value does
evaluate?
                     Exercise 4.27: Let L1, L2 be two MuPAD lists of equal length. How can you find
                     out whether L1[i] < L2[i] holds true for all list elements?
    4-48
                                                                                                Strings
Strings
          Strings are pieces of text, which may be used for formatted screen output. A string
          is a sequence of arbitrary symbols enclosed in “string delimiters” ". Its domain
          type is DOM_STRING.
           string1 := "Use * for multiplication";
           string2 := ", ";
           string3 := "use ^ for exponentiation."
              ”Use * for multiplication”
”, ”
          The dot operator is a short form of the MuPAD® function _concat, which
          concatenates (arbitrarily many) strings:
           _concat("This is ", "a string", ".")
              ”This is a string.”
          When using a range as index, substrings are returned; negative indices count from
          the end of the string:
           string4[19..21], string4[-15..-8]
              ”cat”, ”exponent”
          You may use the command print to output intermediate results in loops or
          procedures on the screen (Section 12.1). By default, this function prints strings
                                                                                                 4-49
4   MuPAD® Objects
                     with the enclosing double quotes. You may change this behavior by using the
                     option Unquoted:
                      print(string4)
                           "Use * for multiplication, use ^ for exponentiation."
                      print(Unquoted, string4)
                           Use * for multiplication, use ^ for exponentiation.
                     Strings are not valid identifiers in MuPAD, so you cannot assign values to them:
                      "name" := sin(x)
                        Error: Invalid left-hand side in assignment [line 1, col 8]
                     The function expr2text converts a MuPAD object to a string. You can employ this
                     function to customize print commands:
                      i := 7:
                      print(Unquoted, expr2text(i)." is a prime.")
                           7 is a prime.
                      a := sin(x):
                      print(Unquoted, "The derivative of " . expr2text(a) .
                                      " is " . expr2text(diff(a, x)). ".")
                           The derivative of sin(x) is cos(x).
    4-50
                                                                                    Strings
Exercise 4.28: The command anames(All) returns a set of all identifiers that
have a value in the current session. Generate a lexicographically ordered list of
these identifiers.
Exercise 4.29: How can you obtain the “mirror image” of a string? Hint: the
function length returns the number of symbols in a string.
                                                                                      4-51
4   MuPAD® Objects
    Functions
                     The arrow operators -> (a minus sign followed by a “greater than” sign) and -->
                     (two minus signs followed by a “greater than” sign) generate simple objects that
                     represent mathematical functions:
                      f := (x, y) -> x^2 + y^2
                          (x, y) → x2 + y 2
                     The function f can now be called like any system function. It takes two arbitrary
                     input parameters (or “arguments”) and returns the sum of their squares:
                      f(a, b + 1)
                                        2
                          (b + 1) + a2
                     You can define a repeated composition f (f (f (·))) of a function with itself by using
                     the iteration operator @@:
                      fff := f@@3: fff(a)
                                    1
                                1
                           1            +1
                          a+1 +1
    4-52
                                                                                   Functions
Of course, these constructions also work for system functions. For example, the
function abs @ Re computes the absolute value of the real part of a complex
number:
 f := abs@Re: f(-2 + 3*I)
      2
If you try to convert an expression into a function by means of the -> operator,
you will find that it does not quite work:
 h := x -> Expression:
 h(1)
             ( )
      2 x cos x2
Instead, use the long arrow operator -->, which evaluates the right hand side
expression, as explained in Chapter 5 and returns a function, which you can
manipulate further:
 h := x --> Expression;
                 ( )
      x → 2 x cos x2
 h'
               ( )           ( )
      x → 2 cos x2 − 4 x2 sin x2
                                                                                       4-53
4   MuPAD® Objects
                     The operator -> is useful for defining functions whose return value can be
                     obtained by simple operations. Functions implementing more complex
                     algorithms usually require many commands and auxiliary variables to store
                     intermediate results. In principle, you can define such functions via -> as well.
                     However, this has the drawback that you often use global variables. Instead, we
                     recommend to define a procedure via proc() begin ... end_proc. This concept
                     of the MuPAD programming language is much more flexible and is discussed in
    4-54
                                                                                      Functions
                                                                 √
Exercise 4.30: Define the functions f (x) = x2 and g(x) =         x. Compute
f (f (g(2)) and f (f (. . . f (x) . . . )) .
                | {z }
                100 times
Exercise 4.31: Define a function that reverses the order of the elements in a list.
Compute the values of T2 (x), . . . , T5 (x) for x = 1/3, x = 0.33, and for a symbolical
value x.
                                                                                           4-55
4   MuPAD® Objects
    Series Expansions
                     Expressions such as 1/(1 - x) admit series expansions for symbolic parameters.
                     This particularly simple example is the sum of the geometric series:
                                                1
                                                   = 1 + x + x2 + x3 + · · ·
                                               1−x
                     The function taylor computes the leading terms of such series:
                      t := taylor(1/(1 - x), x = 0, 9)
                                                                     ( )
                         1 + x + x2 + x3 + x4 + x5 + x6 + x7 + x8 + O x9
                     This is the Taylor series expansion of the expression around the point x = 0, as
                     requested by the second argument. MuPAD® has truncated the infinite series
                     before the term x9 and has collected the tail in the “big Oh” term O(x9 ) (also
                     called the “Landau symbol”). The (optional) third argument of taylor controls
                     the truncation. If it is not present, then MuPAD uses the value of the environment
                     variable ORDER instead, whose default value is 6:
                      t := taylor(1/(1 - x), x = 0)
                                                      ( )
                         1 + x + x2 + x3 + x4 + x5 + O x6
                     The resulting series looks like an ordinary sum with an additional O(·) term.
                     Internally, however, it is represented by a special data structure of domain type
                     Series::Puiseux
                      domtype(t)
                         Series::Puiseux
                     The big-Oh term itself is a data structure on its own, of domain type O and with
                     special rules of manipulation:
                      2*O(x^2) + O(x^3), x^2*O(x^10), O(x^5)*O(x^20),
                      diff(O(x^3), x)
                          ( )    ( )     ( )     ( )
                         O x2 , O x12 , O x25 , O x2
                     The ordering of the terms in a Taylor series is fixed: powers with smaller
                     exponents precede those with higher exponents. This is in contrast to the ordering
                     in ordinary sums, where high exponents precede small exponents:
    4-56
                                                                         Series Expansions
 S := expr(t)
    x5 + x4 + x3 + x2 + x + 1
Here we have used the system function expr to convert the series to an expression
of domain type DOM_EXPR. As you can see in the output, the O(·) term has been cut
off.
The op command acts on series in a non-obvious way and should not be used:
 op(t)
    0, 1, 0, 6, [1, 1, 1, 1, 1, 1] , x = 0, Undirected
Therefore, the function coeff is provided to extract the coefficients. This is more
intuitive than op. The call coeff(t, i) returns the coefficient of xi :
 t := taylor(cos(x^2), x, 20)
         x4   x8   x12   x16    ( )
    1−      +    −     +     + O x20
         2    24 720 40320
 coeff(t, 0), coeff(t, 1), coeff(t, 12), coeff(t, 25)
               1
    1, 0, −       , FAIL
              720
                                                                                      4-57
4   MuPAD® Objects
                     Both the composition operator @ and the iteration operator @@ apply to series as
                     well:
                      a := taylor(sin(x), x, 20):
                      b := taylor(arcsin(x), x, 20): a@b
                              ( )
                         x + O x21
                     If you try to compute the Taylor series of a function that does not have one, then
                     taylor aborts with an error. The function series can compute more general
                     expansions (Laurent series, Puiseux series):
                      taylor(cos(x)/x, x = 0, 10)
                        Error: 1/x*cos(x) does not have a Taylor series \
                        expansion, try 'series' [taylor]
                      series(cos(x)/x, x = 0, 10)
                          1 x x3   x5   x7     ( )
                           − +   −    +     + O x9
                          x 2  24 720 40320
    4-58
                                                                                 Series Expansions
Exercise 4.34: Besides the arithmetical operators, some other system functions
such as diff or int work directly for series. Compare the result of
taylor(diff(1/(1 - x), x), x) and the derivative of taylor(1/(1 - x), x).
Mathematically, both series are identical. Can you explain the difference in
MuPAD?
                                       √       √
Exercise 4.35: The function f (x) = x + 1 − x − 1 tends to zero for large x,
                                                              √
i.e., limx→∞ f (x) = 0. Show that the approximation f (x) ≈ 1/ x is valid for large
values of x. Find better asymptotic approximations of f .
Exercise 4.36: Compute the first three terms in the series expansion of the
function f:= sin(x + x^3) around x = 0. Read the help page for the MuPAD
function revert. Use this function to compute the leading terms of the series
expansion of the inverse function f −1 (which is well-defined in a certain
neighborhood of x = 0).
                                                                                             4-59
4   MuPAD® Objects
                     We consider the residue class ring of integers modulo n. Its elements are the
                     integers 0, 1, . . . , n − 1, and addition and multiplication are defined “modulo n.”
                     This works by adding or multiplying in Z, dividing the result by n, and taking the
                     remainder of this division in {0, 1, . . . , n − 1}:
7 Dom::Real is for symbolic representations of real numbers, while Dom::Float represents them as
floating-point numbers.
    4-60
                                                             Algebraic Structures: Fields, Rings, etc.
 3*5 mod 7
     1
In this example, we have used the data types of the MuPAD kernel: the operator *
multiplies the integers 3 and 5 in the usual way to get 15, and the operator mod
computes the decomposition 15 = 2 · 7 + 1 and returns 1 as remainder modulo 7.
Alternatively, you may tell MuPAD that you want to compute in Z7 = Z/7 Z by
using the input syntax Dom::IntegerMod(7). The latter object acts as a
constructor for elements of the residue class ring8 modulo 7:
 constructor := Dom::IntegerMod(7):
 x := constructor(3); y := constructor(5)
     3 mod 7
5 mod 7
As you can see from the screen output, the identifiers x and y do not have the
integers 3 and 5, respectively, as values. Instead, the numbers are elements of the
residue class ring of integers modulo 7:
 domtype(x), domtype(y)
     Z7 , Z7
Now, you can use the usual arithmetic operations, and MuPAD automatically uses
the computation rules of the residue class ring:
 x*y, x^123*y^17 - x + y
     1 mod 7, 6 mod 7
The ring Dom::IntegerMod(7) even has a field structure, so that you can divide by
all ring elements except 0 mod 7:
8 If you want to execute only a small number of modulo operations, it is often preferable to use
the operator mod, which is implemented in the MuPAD kernel and quite fast. This approach may
require some additional understanding how the system functions work. For example, the compu-
tation of 17^29999 mod 7 takes quite a long time, since MuPAD first computes the very big num-
ber 1729999 and then reduces the result modulo 7. In this case, the computation x^29999, where
x:= Dom::IntegerMod(7)(17), is much faster since the internal modular arithmetic avoids such big
numbers. Alternatively, the call powermod(17, 29999, 7) uses the system function powermod to com-
pute the result quickly without employing Dom::IntegerMod(7).
                                                                                                       4-61
4   MuPAD® Objects
                      x/y
                         2 mod 7
    4-62
                                                    Algebraic Structures: Fields, Rings, etc.
 x + y
         a              b
             2   +             2
     (a + b)         (a + b)
If you supply the system function normal instead, the result is simplified
automatically (Section 9.1):
 constructor := Dom::ExpressionField(normal, iszero):
 x := constructor(a/(a + b)^2):
 y := constructor(b/(a + b)^2):
 x + y
      1
     a+b
We note that the purpose of such MuPAD domains is not necessarily the direct
generation of data structures or the computation with the corresponding objects.
Indeed, some constructors simply return objects of the underlying kernel
domains, if such domains exist:
 domtype(Dom::Integer(2)),
 domtype(Dom::Rational(2/3)),
 domtype(Dom::Float(PI)),
 domtype(Dom::ExpressionField(id, iszero)(a + b))
    DOM_INT, DOM_RAT, DOM_FLOAT, DOM_EXPR
In these cases, there is no immediate benefit in using such a constructor; you may
as well compute directly with the corresponding kernel objects. The main
application of such special data structures is the construction of more complex
mathematical structures. A simple example is the generation of matrices
(Section 4.15) or polynomials (Section 4.16) with entries in a particular ring, such
that matrix or polynomial arithmetic, respectively, is performed according to the
computation rules of the coefficient ring.
                                                                                       4-63
4   MuPAD® Objects
    4-64
                                                                     Vectors and Matrices
We explain the general concept. MuPAD provides the data type Dom::Matrix for
matrices of arbitrary dimension m × n. The type Dom::SquareMatrix represents
square matrices of dimension n × n. They belong to the library Dom, which also
comprises data types for mathematical structures such as rings and fields
(Section 4.14). Matrices may have entries from a set that must be equipped with a
ring structure in the mathematical sense. For example, you may use the
predefined rings and fields such as Dom::Integer, Dom::IntegerMod(n), etc. from
the Dom library.
The call Dom::Matrix(R) creates the constructor for matrices of arbitrary
dimension m × n with coefficients in the ring R. When you construct such a
matrix, you are required to ensure that its entries belong to (or may be converted
to) this ring. You should keep this in mind when trying to generate matrices with
entries outside the coefficient ring in a computation (for example, the inverse of
an integer matrix in general has non-integral rational entries).
The following example yields the constructor for matrices with rational number
entries:
 constructor := Dom::Matrix(Dom::Rational)
    Dom::Matrix(Q)
When generating a matrix, you may supply a function f that takes two arguments.
Then the entry in row i and column j is initialized with f (i, j):
 f := (i, j) -> (i*j):      A := constructor(2, 3, f)
    (           )
        1 2 3
        2 4 6
                                                                                     4-65
4   MuPAD® Objects
                     Alternatively, you can initialize a matrix by specifying a (nested) list. Each list
                     element is itself a list and corresponds to one row of the matrix. The following
                     command generates the same matrix as in the previous example:
                      constructor(2, 3, [[1, 2, 3], [2, 4, 6]]):
                     The parameters for the dimension are optional here, since they are also given by
                     the structure of the list. Thus,
                      constructor([[1, 2, 3], [2, 4, 6]]):
                     also returns the same matrix. An array of domain type DOM_ARRAY (Section 4.9) is
                     also valid for initializing a matrix:
                      Array := array(1..2, 1..3, [[1, 2, 3], [2, 4, 6]]):
                      Mat := constructor(Array):
                     You may define column and row vectors as m × 1 and 1 × n matrices, respectively.
                     Plain lists can be used for defining column or row vectors:
                      column := constructor(3, 1, [1, 2, 3])
                             
                            1
                           
                           2 
                              3
    4-66
                                                                     Vectors and Matrices
The entries of a matrix or a vector may be accessed in the forms matrix[i, j],
row[i], or column[j]. Since vectors are special matrices, you may access the
components of a vector also in the form row[1, i] or column[j, 1], respectively:
 A[2, 3], row[3], row[1, 3],
 column[2], column[2, 1]
    6, 3, 3, 2, 2
You can use loops (Chapter 15) to change all components of a matrix:
 m := 2: n := 3: Mat := constructor(m, n):
 for i from 1 to m do
   for j from 1 to n do
     Mat[i, j] := i*j
   end_for
 end_for:
You can generate diagonal matrices by supplying the option Diagonal. In this
case, the third argument to the constructor may either be a list of the diagonal
elements or a function f such that the i-th diagonal element is f (i):
 constructor(2, 2, [11, 12], Diagonal)
    (             )
        11    0
        0    12
                                                                                    4-67
4   MuPAD® Objects
                     The constructor considered so far returns matrices with rational (i.e., real)
                     number entries. Thus, the following attempt to generate a matrix with complex
                     coefficients does not work:
                      constructor([[1, 2, 3], [2, 4, 1 + I]])
                        Error: unable to define matrix over Dom::Rational \
                         [(Dom::Matrix(Dom::Rational))::new]
                     You have to choose a suitable coefficient ring to generate a matrix with the above
                     entries. In the following example, we define a new constructor for matrices with
                     complex number entries:
                      constructor := Dom::Matrix(Dom::Complex):
                      constructor([[1, 2, 3], [2, 4, 1 + I]])
                          (                      )
                                1 2          3
                                2 4 1+i
                     You may generate matrices whose entries are arbitrary MuPAD expressions by
                     means of the field Dom::ExpressionField(id, iszero) (see Section 4.14). This is
                     the standard coefficient ring for matrices. You may always use this ring when the
                     coefficients and their properties are irrelevant.
    4-68
                                                                    Vectors and Matrices
                                                                                   4-69
4   MuPAD® Objects
                     You can use the standard arithmetical operators for doing basic arithmetic with
                     matrices:
                      A := matrix([[1, 2], [3, 4]]):
                      B := matrix([[a, b], [c, d]]):
                      A + B, A*B;
                      A*B - B*A, A^2 + B
                         (                      ) (                         )
                             a+1 b+2                      a + 2c   b + 2d
                                                  ,
                             c+3 d+4                      3a + 4c 3b + 4d
                         (                                         ) (                   )
                               2c − 3b    2d − 3b − 2a                   a + 7 b + 10
                                                                    ,
                             3a + 3c − 3d   3b − 2c                      c + 15 d + 22
    4-70
                                                                     Vectors and Matrices
An inversion returns FAIL when MuPAD is unable to compute the result. The
following matrix is not invertible:
 C := matrix([[1, 1], [1, 1]]):
 C^(-1)
    FAIL
                                                                                    4-71
4   MuPAD® Objects
                     The linear algebra library linalg and the numerics library numeric (Section 4.15)
                     comprise many other functions for handling matrices.
                        10 norm(A, 1)            returns the one-norm,   norm(A, Frobenius)   yields the Frobenius norm
                     (∑               )1/2
                             |Aij |
                                  2
                                             .
                       i,j
    4-72
                                                                     Vectors and Matrices
Since the domain is attached to the object A as A::dom, one can also call the
domain methods via A::dom::method. For example:
 A::dom::tr(A)
    x+y
                                                                                    4-73
4   MuPAD® Objects
                        -- Interface:
                        linalg::addCol,                           linalg::addRow,
                        linalg::adjoint,                          linalg::angle,
                        linalg::basis,                            linalg::charmat,
                        linalg::charpoly,                         linalg::col,
                        linalg::companion,                        linalg::concatMatrix,
                        linalg::crossProduct,                     linalg::curl,
                        linalg::delCol,                           linalg::delRow,
                        linalg::det,                              linalg::divergence,
                        linalg::eigenvalues,                      linalg::eigenvectors,
                        linalg::expr2Matrix,                      linalg::factorCholesky,
                        linalg::factorLU,                         linalg::factorQR,
                        linalg::frobeniusForm,                    linalg::gaussElim,
                        linalg::gaussJordan,                      linalg::grad,
                        linalg::hermiteForm,                      linalg::hessenberg,
                        linalg::hessian,                          linalg::hilbert,
                        linalg::intBasis,                         linalg::inverseLU,
                        linalg::invhilbert,                       linalg::invpascal,
                        linalg::invvandermonde,                   linalg::isHermitean,
                        linalg::isPosDef,                         linalg::isUnitary,
                        linalg::jacobian,                         linalg::jordanForm,
                        linalg::kroneckerProduct,                 linalg::laplacian,
                        linalg::matdim,                           linalg::matlinsolve,
                        linalg::matlinsolveLU,                    linalg::minpoly,
                        linalg::multCol,                          linalg::multRow,
                        linalg::ncols,                            linalg::nonZeros,
                        linalg::normalize,                        linalg::nrows,
                        linalg::nullspace,                        linalg::ogCoordTab,
                        linalg::orthog,                           linalg::pascal,
                        linalg::permanent,                        linalg::potential,
                        linalg::pseudoInverse,                    linalg::randomMatrix,
                        linalg::rank,                             linalg::row,
    4-74
                                                                  Vectors and Matrices
   linalg::scalarProduct,          linalg::setCol,
   linalg::setRow,                 linalg::smithForm,
   linalg::stackMatrix,            linalg::submatrix,
   linalg::substitute,             linalg::sumBasis,
   linalg::swapCol,                linalg::swapRow,
   linalg::sylvester,              linalg::toeplitz,
   linalg::toeplitzSolve,          linalg::tr,
   linalg::transpose,              linalg::vandermonde,
   linalg::vandermondeSolve,       linalg::vecdim,
   linalg::vectorOf,               linalg::vectorPotential,
   linalg::wiedemann
                                                                                   4-75
4   MuPAD® Objects
                     The numerics library numeric (see ?numeric) contains many functions for
                     numerical computations with matrices:
                                                                                              
                                  numeric::det             : determinant
                                  numeric::expMatrix       : exp(Matrix)
                                  numeric::factorCholesky : Cholesky factorization
                                  numeric::factorLU        : LU factorization
                                  numeric::factorQR        : QR factorization
                                  numeric::fMatrix         : functional calculus
                                  numeric::inverse         : inversion
                                  numeric::eigenvalues     : eigenvalues
                                  numeric::eigenvectors    : eigenvalues and –vectors
                                  numeric::singularvalues : singular values
                                  numeric::singularvectors : singular values and vectors
                                                                                              
                     Partially, these routines work for matrices with symbolic entries of type
                     Dom::ExpressionField and then are more efficient for large matrices than the
                     linalg functions. However, the latter can handle arbitrary coefficient rings.
                                                                                           
                                                                                      1ab
                     Exercise 4.38: Find the values of a, b, c for which the matrix  1 1 c  is not
                                                                                      111
                     invertible.
    4-76
                                                                     Vectors and Matrices
Compute its determinant, its characteristic polynomial, and its eigenvalues. For
each eigenvalue, compute a basis of the corresponding eigenspace.
Sparse Matrices
The internal storage of matrices is optimized for sparse data, i.e., for matrices
consisting largely of zeroes, since such matrices appear often in practice. Here are
some remarks concerning efficiency when your matrices are large and sparse:
Lists of equations can be used to specify the entries when creating a matrix. The
following matrix A of dimension 1000 × 1000 consists of a diagonal band and two
additional entries in the upper right and the lower left corner. We display some
entries of its 10-th power:
 n := 1000:
 A := matrix(n, n, [(i, i) = i $ i = 1..n,
                    (n, 1) = 1, (1, n) = 1]):
 B := A^10:
 B[1, 1], B[1, n]
    1002010022050086122130089, 1001009015040066101119105055
                                                                                       4-77
4   MuPAD® Objects
                     Here we have applied the inverse 1/A of A to the right-hand side of the equation.
                     Note, however, that inverting a sparse matrix is not a good idea because the
                     inverse of a sparse matrix is, in general, not sparse. It is much more efficient to
                     use sparse matrix factorization to compute the solution of a sparse system of
                     linear equations. We use the linear solver numeric::matlinsolve with the option
                     Symbolic to compute the solution of a sparse system representing 1000 equations
                     for 1000 unknowns. The numeric routine employs sparsity in an optimal way:
                      A := matrix(1000, 1000, [-1, 2, -1], Banded):
                      b := matrix(1000, 1, [1 $ 1000]):
                      [x, kernel] := numeric::matlinsolve(A, b, Symbolic):
An Application
                     We want to compute the symbolic solution a(t), b(t) of the system of second order
                     differential equations
                                       2                        2
                                   d              d           d                d
                                       a(t) = 2 c    b(t) ,        b(t) = −2 c    a(t) + 3 c2 b(t)
                                   dt2            dt          d t2             dt
                     with an arbitrary constant c. Writing a′ (t) = ddt a(t), b′ (t) = ddt b(t), these equations
                     may be equivalently written as a system of first order differential equations in the
    4-78
                                                                                                    Vectors and Matrices
The solution of this system is given by applying the exponential matrix etA to the
initial condition x(0):
                                   x(t) = etA x(0) .
 delete c, t:
 A := matrix([[0, 1,     0,    0 ],
              [0, 0,     0,   2*c],
              [0, 0,     0,    1 ],
              [0, -2*c, 3*c^2, 0 ]]):
To simplify this matrix, we use the function Simplify, which for matrices simply
maps itself to the entries:
 B := Simplify(B)
                                                                                         
               4 sin(c t)
           1                − 3t    6 c t − 6 sin(c t)               − 2 (cos(cc t)−1)
                  c                                                                      
        0     4 cos(c t) − 3      −6 c (cos(c t) − 1)                  2 sin(c t)        
                                                                                         
               2 (cos(c t)−1)                                             sin(c t)       
        0             c             4 − 3 cos(c t)                           c           
         0      −2 sin(c t)                  3 c sin(c t)                cos(c t)
                                                                                                                   4-79
4   MuPAD® Objects
                     We assign a symbolic initial condition to the vector x0 . The following call creates a
                     4 × 1 matrix to be interpreted as a column vector:
                      x_0 := matrix([a_0, a_0', b_0, b_0'])
                                 
                             a0
                          ′ 
                          a0 
                              
                              
                          b0 
                           b′0
                     The solution functions a(t) and b(t) with the symbolic initial conditions a(0) = a0 ,
                     a′ (0) = a′0 , b(0) = b0 , b′ (0) = b′0 are:
                      a := t --> expand(x(t)[1]): a(t)
                                                          2 b′0   2 cos(c t) b′0   4 a′0 sin(c t)
                         a0 − 6 b0 sin(c t) − 3 t a′0 +         −                +                + 6 b0 c t
                                                           c           c                  c
                      b := t --> expand(x(t)[3]): b(t)
                                                  2 a′0   2 cos(c t) a′0  b′ sin(c t)
                         4 b0 − 3 b0 cos(c t) −         +                + 0
                                                    c          c               c
                     Finally, we check that the above expressions really solve the system of differential
                     equations:
                      expand(diff(a(t),t,t) - 2*c*diff(b(t),t)),
                      expand(diff(b(t),t,t) + 2*c*diff(a(t),t) - 3*c^2*b(t))
                         0, 0
    4-80
                                                                                                 Polynomials
Polynomials
              Computation with polynomials is an important task for a computer algebra
              system. Of course, you may realize a polynomial in MuPAD® as an expression in
              the sense of Section 4.4 and use the standard arithmetic:
               polynomialExpression := 1 + x + x^2:
               expand(polynomialExpression^2)
                   x4 + 2 x3 + 3 x2 + 2 x + 1
              However, there exists a special data type DOM_POLY together with some kernel and
              library functions, which simplifies such computations and makes them more
              efficient.
Definition of Polynomials
                                                                                                         4-81
4   MuPAD® Objects
                     If you do not specify a list of indeterminates, then poly calls the function indets
                     to determine all symbolic identifiers in the expression and interprets them as
                     indeterminates of the polynomial:
                      indets(a_0 + a_1*x + a_2*x^2, PolyExpr)
                         {a0 , a1 , a2 , x}
                      poly(expression, [x])
                             (                                       )
                         poly (π + 1) x2 + (a + 1) x + (1 − b) , [x]
                     You can see that MuPAD collects the coefficients of equal powers of the
                     indeterminate. The terms are sorted according to falling exponents.
                     Instead of using an expression, you may also generate a polynomial by specifying
                     a list of the non-zero coefficients together with the respective exponents. The
                                                                              ∑k
                     command poly(list, [x]) generates the polynomial i=0 ai xni from the list
                     [[a0 , n0 ], [a1 , n1 ], . . . , [ak , nk ]]:
                      list := [[1, 0], [a, 3], [b, 5]]: poly(list, [x])
                             (                     )
                         poly b x5 + a x3 + 1, [x]
    4-82
                                                                                             Polynomials
For more abstract computations, you may want to restrict the coefficients of a
polynomial to a certain set (mathematically: a ring) which is represented by a
special data structure. We have already seen typical examples of rings and their
corresponding MuPAD domains in Section 4.14: the integers Dom::Integer, the
rational numbers Dom::Rational, or the residue class ring Dom::IntegerMod(n)
of integers modulo n. You may specify the coefficient ring as argument to poly:
 poly(x + 1, [x], Dom::Integer)
     poly (x + 1, [x] , Z)
Note that in the last example, the system has automatically simplified the
coefficients according to the rules for computing with integers modulo 3:12
 4 mod 3, 11 mod 3
     1, 2
12 For polynomials, you may also use IntMod(3) instead of Dom::IntegerMod(3), in the form
poly(4 * x + 11, [x], IntMod(3)). Then the integers modulo 3 are represented by −1, 0, 1 and not, as
for Dom::IntegerMod(3), by 0, 1, 2. Polynomial arithmetic is much faster when you use IntMod(3).
                                                                                                       4-83
4   MuPAD® Objects
                     If no coefficient ring is specified, then MuPAD by default uses the ring Expr which
                     symbolizes arbitrary MuPAD expressions. In this case, you may use symbolic
                     identifiers as coefficients:
                      polynomial := poly(a + x + b*y, [x, y]);
                      op(polynomial)
                          poly (x + b y + a, [x, y])
a + x + b y, [x, y] , Expr
                     These are the three operands of a MuPAD polynomial p, which can be accessed via
                     op(p, 1), op(p, 2), and op(p, 3), respectively. Thus, you may convert a
                     polynomial to a mathematically equivalent expression13 of domain type DOM_EXPR
                     by
                      expression := op(polynomial, 1):
                     However, you should preferably use the system function expr, which can convert
                     various domain types such as polynomials to expressions:
                      polynomial := poly(x^3 + 5*x + 3)
                              (                  )
                          poly x3 + 5 x + 3, [x]
                      op(polynomial, 1) = expr(polynomial)
                          x3 + 5 x + 3 = x3 + 5 x + 3
13 If the polynomial is defined over a ring other than Dom::ExpressionField or Expr, the result may
not be equivalent.
    4-84
                                                                                 Polynomials
                                                                                       4-85
4   MuPAD® Objects
                     The result is a sequence with two operands: the quotient and the remainder of the
                     division:
                      [quotient, remainder] := [divide(p, q)]:
                     We check:
                      p = quotient*q + remainder
                             (           )      (            )
                         poly x3 + 1, [x] = poly x3 + 1, [x]
                     The polynomial denoted by remainder is of lower degree than q, which makes the
                     decomposition p = quotient * q + remainder unique. Dividing two polynomials by
                     means of the usual division operator / is only allowed in the special case when the
                     remainder that divide would return vanishes:
                      p := poly(x^2 - 1): q := poly(x - 1): p/q
                         poly (x + 1, [x])
                     Note that the arithmetic operators process only polynomials of exactly identical
                     types:
                      poly(x + y, [x, y]) + poly(x^2, [x, y]),
                      poly(x) + poly(x, [x], Expr)
                             (                  )
                         poly x2 + x + y, [x, y] , poly (2 x, [x])
                     Both the list of indeterminates and the coefficient ring must coincide. Otherwise
                     the system errors.
                     The polynomial arithmetic performs coefficient additions and multiplications
                     according to the rules of the coefficient ring:
                      p := poly(4*x + 11, [x], Dom::IntegerMod(3)):
    4-86
                                                                               Polynomials
 p; p + p; p*p
    poly (x + 2, [x] , Z3 )
    poly (2 x + 1, [x] , Z3 )
         (                    )
    poly x2 + x + 1, [x] , Z3
You can also use the more general evaluation operator | for the same effect:
 p | x = 0; p | [x = 0, y = 2]
    poly (y, [y])
You may also regard a polynomial as a function of the indeterminates and call this
function with arguments:
                                                                                     4-87
4   MuPAD® Objects
                      p(2, z)
                         z+4
                      factor(poly(x^2 + 1, Dom::IntegerMod(2)))
                                                2
                         poly (x + 1, [x] , Z2 )
    4-88
                                                                             Polynomials
Table 4.6 is a summary of the operations for polynomials discussed above. Section
“Functions for Polynomials” of the MuPAD Quick Reference lists further functions
for polynomials in the standard library. The groebner library comprises functions
for handling multivariate polynomial ideals (see ?groebner).
                                                                                     4-89
4   MuPAD® Objects
                                                                         
                          +, -, *, ^  : arithmetic
                          coeff       : extract coefficients
                          degree      : polynomial degree
                          diff, D     : differentiation
                          divide      : division with remainder
                          evalp       : evaluation
                          expr        : conversion to expression
                          factor      : factorization
                          gcd         : greatest common divisor
                          mapcoeffs : apply a function
                          multcoeffs : multiplication by a scalar
                          nterms      : number of non-zero coefficients
                          nthcoeff    : n-th coefficient
                          nthmonomial : n-th monomial
                          nthterm     : n-th term
                          poly        : construct a polynomial
                          poly2list : conversion to list
                                                                         
                                       ®
                     Table 4.6: MuPAD functions operating on polynomials
    4-90
                                                                                 Hardware Float Arrays
             Most of the numeric library accepts hardware floating point arrays as inputs and
             returns objects of the same type:
              B := numeric::fft(A): domtype(B)
                 DOM_HFARRAY
              numeric::eigenvalues(A)
                 [5.173121022, 0.8239615051, 0.3962245484 + 0.3259514491 i, . . . ]
                                                                                                 4-91
4   MuPAD® Objects
                      A + A; A*B
                                              
                           2.0 4.0 6.0 8.0
                                              
                          10.0 12.0 14.0 16.0 
                           18.0 20.0 22.0 24.0
                                          
                           2.716666667 2.1
                                          
                              7.85    5.9 
                           12.98333333 9.7
    4-92
                                                                                                         Interval Arithmetic
Interval Arithmetic
              There is another kernel data type, called DOM_INTERVAL. Objects of this type
              represent real or complex intervals of floating-point numbers. They provide,
              among other possibilities, a means of controlling one of the most fundamental
              problems of floating-point arithmetic: round-off errors.
              The basic idea is as follows: Instead of floating-point numbers x1 , x2 etc., where
              almost each operation leads to (usually small) errors, consider intervals X1 , X2
              etc. which are known to contain the precise numbers coming from the application.
              One would like to have a verified statement that the value y = f (x1 , x2 , . . . ) of a
              function f lies in some interval Y . Mathematically, the image set
Y = f (X1 , X2 , . . . ) = {f (ξ1 , ξ2 , . . . ); ξ1 ∈ X1 ; ξ2 ∈ X2 ; . . .}
              is wanted. Computing this image set exactly is a formidable task. In fact, it is too
              ambitious to ask for an exact representation when using fast and memory efficient
              floating-point arithmetic. Instead, the interval version of a function f is an
              algorithm fˆ that produces a larger set fˆ(X1 , X2 , . . . ) which is guaranteed to
              contain the exact image set of f :
f (X1 , X2 , . . . ) ⊂ fˆ(X1 , X2 , . . . ).
                                                                                                                      4-93
4   MuPAD® Objects
                     The MuPAD® functions that support interval arithmetic include the basic
                     arithmetical operations +, -, *, /, ^ as well as most of the special functions such as
                     sin, cos, exp, ln, abs etc.:
                      X1^2 + X2
                          8.869604401 . . . 9.695956224
                      X1 - I*X2 + X3
                          (5.141592653 . . . 7.141592654) + i (−2.826351823 . . . 6.0)
                      sin(X1) + exp(abs(X3))
                          7.389056098 . . . 603.728285
                     The last example shows that the arithmetic may produce “symbolic” unions of
                     floating-point intervals. Actually, the union is still of type DOM_INTERVAL:
                      domtype(%)
                          DOM_INTERVAL
    4-94
                                                                           Interval Arithmetic
In fact, the functions union and intersect for creating unions and intersections of
sets can be used for creating intervals (which are, after all, a special kind of sets):
 X1 union X2^2
     0.0301536896 . . . 1.0 ∪ 3.141592653 . . . 3.141592654
 cos(X1*X2) intersect X2
     −1.0 . . . − 0.1736481776
Symbolic objects such as identifiers (Chapter 4.3) and floating point intervals can
be mixed. The function interval replaces all numerical subexpressions of an
expression (Chapter 4.4) by floating-point intervals:
 interval(2*x^2 + PI)
     (2.0 . . . 2.0) x2 + (3.141592653 . . . 3.141592654)
                                                                                          4-95
4   MuPAD® Objects
                     In particular, the set of all floating point intervals is not only regarded as a ring,
                     but even as a field. Strictly speaking, however, these mathematical categories are
                     not really adequate for interval objects. For example, subtracting an interval from
                     itself does not yield the zero element (the neutral element with respect to
                     addition):
                      (2 ... 3) - (2 ... 3)
                          −1.0 . . . 1.0
    4-96
                                                                            Interval Arithmetic
 B := 1/Dom::Matrix(Dom::FloatIV)(A)
      array(1..8, 1..8,
        (1, 1) = -73.29144677 ... 201.2914468,
              ...
        (3, 2) = -955198.1290 ... -949921.8709,
              ...
        (8, 8) = 176679046.2 ... 176679673.8
      )
The entries of the inverse are guaranteed to lie in the indicated intervals. The
component (8, 8) is determined to a precision of 6 leading decimal digits, whereas
the component (1, 1) is only known to lie somewhere between −73.29 and 201.3.
Note, however, that the generic inversion algorithm tends to overestimate the
intervals drastically. The results returned by a numerical inversion with
“standard” floating-point numbers might actually be more accurate than
predicted by this interval computation.
The exact components of the inverse are available, too. All entries of inverse
Hilbert matrices are integers:
 C := linalg::invhilbert(8)
      array(1..8, 1..8,
        (1, 1) = 64,
              ...
        (3, 2) = -952560,
              ...
        (8, 8) = 176679360
      )
                                                                                            4-97
4   MuPAD® Objects
                     The MuPAD object NIL, which is distinct from null(), intuitively means “no
                     value.” Some system functions return the NIL object when you call them with
                     arguments for which they need not compute anything. A typical example are
                     uninitialized operands of arrays:
                      A := array(1..2): op(A, 1)
                         NIL
                     Uninitialized local variables and parameters of MuPAD procedures also have the
                     value NIL (Section 17.4).
                     The MuPAD object FAIL intuitively means “I could not find a value.” System
                     functions return this object when there is no meaningful result for the given input
                     parameters.
    4-98
                                              Null Objects: null(), NIL, FAIL, undefined
 A^(-1)
    FAIL
Another object with a similar meaning is undefined. For example, the MuPAD
function limit returns this object when the requested limit does not exist:
 limit(1/x, x = 0)
    undefined
                                                                                   4-99
                                                                               5
              Since the identifiers a and x only represent themselves, the “value” of y is the
              symbolic expression a + x. We have to distinguish carefully between the identifier
              y and its value. More precisely, the value of an identifier denotes the MuPAD®
              object that the system computes by evaluation and simplification of the
              right-hand side of the assignment identifier:= value at the time of assignment.
              Note that in the example above, the value of y is composed of the symbolic
              identifiers a and x, which may be assigned values at a later time. For example, if
              we assign the value 1 to the identifier a, then a is replaced by its value 1 in the
              expression a + x, and the call y returns x + 1:
               a := 1: y
                  x+1
              We say that the evaluation of the identifier y returns the result x + 1, but its value
              is still a + x:
                         If we now assign the value 2 to x, then both a and x are replaced by their values at
                         the next evaluation of y. Hence we obtain the sum 2 + 1 as a result, which MuPAD
                         automatically simplifies to 3:
                          x := 2: y
                              3
                         Here are some further examples for this mechanism. We first assign the rational
                         number 1/3 to x, then we assign the object [x, x^2, x^3] to the identifier list. In
                         the assignment, the system evaluates the right-hand side and automatically
                         replaces the identifier x by its value. Thus, at the time of assignment, the identifier
                         list gets the value [1/3, 1/9, 1/27] and not [x, x2 , x3 ]:
    5-2
                                                               Identifiers and Their Values
 delete x: list
     [            ]
         1 1 1
          , ,
         3 9 27
When evaluating y, the system replaced the identifier f by its value, which is the
value of the identifier sin. This is a procedure which is executed when y is
evaluated and returns sin(π) as 0.
                                                                                      5-3
5   Evaluation and Simplification
                         We now explain in greater detail how MuPAD® performs the final evaluation.
                         First (“level 1”) the evaluator considers the value a + x of y. Since this value
                         contains identifiers x and a, a second evaluation step (“level 2”) is necessary to
                         determine the value of these identifiers. The system recognizes that a has the
                         value 1, while x has no value (and thus mathematically represents an unknown).
                         Now the system’s arithmetic combines these results to x + 1, and this is the
                         evaluation of y. Figures 5.1–5.3 illustrate this process. A box represents an
                         identifier and its value (or ·, respectively, if it has no value). An arrow represents
                         one evaluation step.
y · y y
+ x · a · + x · a
                         Figure 5.1: The identifier   Figure 5.2: After the as-       Figure 5.3: After the as-
                         y without a value.           signment y:= a + x.             signment a:= 1, we finally
                                                                                      obtain x + 1 as the evalua-
                                                                                      tion of y.
    5-4
                                             Complete, Incomplete, and Enforced Evaluation
The user may control the levels of this tree via the system function level. We look
at an example:
 delete a, b, c: x := a + b: a := b + 1: b := c:
level 0 : x
level 1 : + a b
level 2 : + b 1 c ·
level 3 : c ·
The identifier x forms the top level (the root, level 0) of its own evaluation tree:
 level(x, 0)
     x
                                                                                       5-5
5   Evaluation and Simplification
                         We call the type of evaluation described here a complete evaluation. This means
                         that identifiers are replaced by their values recursively until no further evaluations
                         are possible. The environment variable LEVEL, which has the default value 100,
                         determines how far MuPAD descends at most in an evaluation tree.
                         More precisely, this means that MuPAD evaluates up to depth LEVEL in interactive
                         mode.1
                          delete a0, a1, a2: LEVEL := 2:
                          a0 := a1: a0
                               a1
                          a1 := a2: a0
                               a2
                         Up to now, the evaluation tree for a0 has depth 2, and the LEVEL value of 2
                         achieves a complete evaluation. However, in the next step, the value of a2 is not
                         taken into account:
                          a2 := a3: a0
                               a2
                         As soon as MuPAD realizes that the current evaluation level exceeds the value of
                         the environment variable MAXLEVEL (whose default value is 100), then it assumes
                         to be in an infinite loop and aborts the evaluation with an error message:
1 One should not confuse this with the effect of a system function call, which may return a not com-
                         pletely evaluated object, such as subs (Chapter 6). The call subs(sin(x), x = 0), for example, returns
                         sin(0) and not 0! The functionality of subs is to perform a substitution and to return the resulting object
                         without further evaluation.
    5-6
                                            Complete, Incomplete, and Enforced Evaluation
 MAXLEVEL := 2: a0
      Error: Recursive definition [See ?MAXLEVEL]
 delete MAXLEVEL:
Compare this to the following statements, where requesting the identifier list
causes the usual complete evaluation:
 delete x: list := [sin(x), cos(x)]: x := 0: list
      [0, 1]
As you can see, the call of A returns the value (the array), but does not replace a, b
by their values. You can evaluate the entries via map(A, eval):
 map(A, eval)
      (         )
          1 1
                                                                                         5-7
5   Evaluation and Simplification
                         Note that in contrast to the above behavior, the indexed access of an individual
                         entry is evaluated completely:
                          A[1], A[2]
                              1, 1
                         Matrices (of type Dom::Matrix(·)), tables (of domain type DOM_TABLE), and
                         polynomials (DOM_POLY) are treated in the same way as arrays. Moreover, within
                         procedures, MuPAD always evaluates only up to level 1 (Section 17.11). If this is
                         not sufficient, you may control this behavior explicitly by means of level.
                         The command hold(object) is similar to level(object, 0) and prevents the
                         evaluation of object.2 This may be desirable in many situations. The following
                         function, which cannot be executed for symbolic arguments, yields an example
                         where the (premature) evaluation is undesirable:
                          absValue := X -> (if X >= 0 then X else -X end_if):
                          absValue(X)
                            Error: Can't evaluate to boolean [_leequal];
                            during evaluation of 'absValue'
                         The reason is that numeric::int internally substitutes numerical values for X, for
                         which absValue can be evaluated without problems.
2 See ?hold for the exact difference between hold(object) and level(object, 0).
    5-8
                                          Complete, Incomplete, and Enforced Evaluation
Here is another example: like most MuPAD functions, the function domtype first
evaluates its argument, so that the command domtype(object) returns the
domain type of the evaluation of object:
 x := 1: y := 1: x, x + y, sin(0), sin(0.1)
    1, 2, 0, 0.09983341665
 domtype(x), domtype(x + y), domtype(sin(0)),
 domtype(sin(0.1))
    DOM_INT, DOM_INT, DOM_INT, DOM_FLOAT
Using hold, you obtain the domain types of the objects themselves: x is an
identifier, x + y is an expression, and sin(0) and sin(0.1) are function calls and
hence expressions as well:
 domtype(hold(x)), domtype(hold(x + y)),
 domtype(hold(sin(0))), domtype(hold(sin(0.1)))
    DOM_IDENT, DOM_EXPR, DOM_EXPR, DOM_EXPR
The commands ?level and ?hold provide further information from the
corresponding help pages.
Exercise 5.1: What are the values of the identifiers x, y, and z after the following
statements? What is the evaluation of the last statement in each case?
 delete a1, b1, c1, x:
 x := a1: a1 := b1: a1 := c1: x
 delete a2, b2, c2, y:
 a2 := b2: y := a2: b2 := c2: y
 delete a3, b3, z:
 b3 := a3: z := b3: a3 := 10: z
                                                                                       5-9
5   Evaluation and Simplification
    Automatic Simplification
                         MuPAD® automatically simplifies many objects such as certain function calls or
                         arithmetical expressions with numbers:
                          sin(15*PI), exp(0), (1 + I)*(1 - I)
                              0, 1, 2
                         The user can neither control nor extend the automatic simplifier.
                         In most cases, however, MuPAD does not automatically simplify expressions. The
                         reason is that the system generally cannot decide which is the most reasonable
                         way of simplification. For example, consider the following expression which is not
                         simplified:
                          y := (-4*x + x^2 + x^3 - 4)*(7*x - 5*x^2 + x^3 - 3)
                               (                   )(                 )
                              − x3 − 5 x2 + 7 x − 3 −x3 − x2 + 4 x + 4
                         Naturally, you can expand this expression, which may be reasonable, for example,
                         before computing its symbolic integral:
                          expand(y)
                              x6 − 4 x5 − 2 x4 + 20 x3 − 11 x2 − 16 x + 12
    5-10
                                                                  Automatic Simplification
However, if you are interested in the roots of the polynomial, it makes more sense
to compute its linear factors:
 factor(y)
                     2
    (x − 3) · (x − 1) · (x − 2) · (x + 2) · (x + 1)
                                                                                      5-11
5   Evaluation and Simplification
                         The MuPAD equation solver solve (Chapter 8) returns the set C of all complex
                         numbers.3 Thus, solve claims that arbitrary complex values of x yield a solution
                         of the equation x/x = 1. The reason is that the system first automatically
                         simplifies the expression x/x to 1, and then in fact solves the equation 1 = 1. The
                         exceptional case x = 0, for which the original problem makes no sense, is
                         completely ignored in the simplified output!
    5-12
                                                                                  Evaluation at a Point
Evaluation at a Point
              There is also another concept commonly known as “evaluation,” namely replacing
              some placeholder (free variable) by a specific value and simplifying the resulting
              expression. This operation is implemented by the function evalAt, which is also
              accessible as the | operator. (The | operator mimics the notation f (x)|x=1
              commonly used in math texts.)
               f := sin(x):
               f | x=0, f | x=1
                  0, sin(1)
              Note that, unlike subs, evalAt respects the mathematical meaning and only
              substitutes free variables, not bound ones:
               delete f:
               F := int(f(x), x=0..infinity) + sin(x):
               subs(F, x = 1), F | x=1
                             ∫    ∞                        ∫   ∞
                  sin(1) +            f (1) d1, sin(1) +           f (x) dx
                              0                            0
                                                                                                   5-13
                                                                      6
a + b cb , 2 c2 + a
         You see that subs returns the result of the substitution, but the identifier f
         remains unchanged. If you represent a map F by the expression f = F (x), then
         you may use subs to evaluate the function at some point:
          f := 1 + x + x^2:
          subs(f, x = 0), subs(f, x = 1),
          subs(f, x = 2), subs(f, x = 3)
             1, 3, 7, 13
         Note, however, that subs (as well as the commands subsex and subsop to be
         handled shortly) performs a purely syntactical replacement, which may lead to
         incorrect results when evaluating a function in this way:
          f := x/sin(x): subs(f, x = 0)
             0
6   Substitution: subs, subsex, and subsop
                         The output of the subs command is subjected to the usual simplifications of the
                         internal simplifier. In the above example, the call subs(f, x = 0) produces the
                         object 1 + 0 + 0^2, which is automatically simplified to 1. You must not confuse this
                         with evaluation (Chapter 5), where in addition all identifiers in an expression are
                         replaced by their values.
                         the identifier sin for the sine function is not replaced by the corresponding
                         MuPAD function, which would return sin(0) = 0. Only the next call to g performs
                         a complete evaluation:
                           g
                               0
    6-2
                                                  Substitution: subs, subsex, and subsop
You may replace arbitrary MuPAD objects by substitution. In particular, you can
substitute functions or procedures as new values:
 eval(subs(h(a + b), h = (x -> 1 + x^2)))
             2
    (a + b) + 1
If you want to replace a system function, enclose its name in a hold command:
 eval(subs(sin(a + b), hold(sin) = (x -> x - x^3/3)))
                           3
                 (a + b)
    a+b−
                    3
Here the sum a + b and the product a * b are not operands of the corresponding
expressions. Even worse, we find:
 f := a + b + sin(a + b): subs(f, a + b = 1)
    a + b + sin(1)
Again, you cannot obtain the subexpression a + b of the outer sum by means of op.
However, the argument of the sine is the sub-operand op(f, [3, 1]) (see
Sections 4.1 and 4.4), and hence it is replaced by 1.
                                                                                    6-3
6   Substitution: subs, subsex, and subsop
                         In contrast to subs, the function subsex also replaces subexpressions in sums and
                         products:
                           subsex(f, a + b = x + y), subsex(a * b * c, a * b = x + y)
                              x + y + sin(x + y) , c (x + y)
                         This kind of substitution requires a closer analysis of the expression tree, and
                         hence subsex is much slower than subs for large objects. When replacing more
                         complex subexpressions, you should not be misled by the screen output of
                         expressions:
                           f := a/(b*c)
                              a
                              bc
                           subs(f, b*c = New), subsex(f, b*c = New)
                               a   a
                                 ,
                              b c New
                         If you look at the operands of f, you see that the expression tree does not contain
                         the product b*c. This explains why no substitution took place in the subs call:
                           op(f)
                                   1 1
                              a,    ,
                                   b c
                         Thus we obtain:
                           subs(a + b^2, a = b, b = a)
                              a2 + a
    6-4
                                                     Substitution: subs, subsex, and subsop
The output of the equation solver solve (Chapter 8) supports the functionality of
subs. In general, solve returns lists of equations, which may be used in subs:
 equations := {x + y = 2, x - y = 1}:
 solution := solve(equations, {x, y})
    {[           ]}
         3     1
      x = ,y =
         2     2
Here, we have replaced the second operand a^2 of the sum by d^5. In the
following example, we first replace the exponent of the second term (this is the
operand [2, 2] of the sum), and then the first term:
 subsop(2*c + a^2, [2, 2] = 4, 1 = x*y)
    a4 + x y
In the following expression, we first replace the first term, yielding the expression
x * y + c^2. Then we substitute z for the second factor of the first term (which now
is y):
 subsop(a*b + c^2, 1 = x*y, [1, 2] = z)
    c2 + x z
                                                                                        6-5
6   Substitution: subs, subsex, and subsop
                         The expression a + 2 is a symbolic sum, which has a 0-th operand, namely, the
                         system function _plus for generating sums:
                           op(a + 2, 0)
                              _plus
                         You can replace this operand by any other function (for example, by the system
                         function _mult which multiplies its arguments):
                           subsop(a + 2, 0 = _mult)
                              2a
                         When using subsop, you need to know the position of the operand that you want
                         to replace. Nonetheless, you should be cautious, since the system may change the
                         order of the operands when this is mathematically valid (for example, in sums,
                         products, or sets):
                           set := {sin(1 + a), a, b, c^2}
                              {                      }
                               a, b, sin(a + 1) , c2
                         If you use subs, you need not know the position of the subexpression. Another
                         difference between subs and subsop is that subs traverses the expression tree of
                         the object recursively, and thus also replaces suboperands:
                           subs(set, a = a^2)
                              {      (      )          }
                               b, sin a2 + 1 , a2 , c2
    6-6
                                                 Substitution: subs, subsex, and subsop
       4 diff(f(x), x, x, x, x, x)
       --------------------------- - ...
              diff(f(x), x)
                                                                                   6-7
                                                                 7
       We have already used the MuPAD® commands for differentiation and integration.
       Since they are important, we recapitulate the usage of these routines here.
7   Differentiation and Integration
    Differentiation
                          The call diff(expression, x) computes the derivative of the expression with
                          respect to the unknown x:
                           diff(sin(x^2), x)
                                      ( )
                               2 x cos x2
                          You can compute partial derivatives in the same way. MuPAD® assumes that
                          mixed partial derivatives of symbolic expressions are symmetric:
                           diff(f(x,y), x, y) - diff(f(x,y), y, x)
                               0
    7-2
                                                                                       Differentiation
Here, id denotes the identity map x → x. The expression D(f)(x) returns the
value of the derivative at a point:
 D(f)(1), D(f)(y^2), D(g)(0)
           ( ( ))
        cos ln y 2
     1,            , g ′ (0)
             y2
The system converts the prime ' for the derivative to a call of D:
 f'(1), f'(y^2), g'(0)
           ( ( ))
        cos ln y 2
     1,            , g ′ (0)
             y2
For a function with more than one argument, D([i], f) is the partial derivative
with respect to the i-th argument, and D([i, j, ...], f) is equivalent to
D([i], D([j], ...)), for higher partial derivatives.
Exercise 7.1: Consider the function f : x → sin(x)/x. Compute first the value of
f at the point x = 1.23, and then the derivative f ′ (x). Why does the following
input not yield the desired result?
 f := sin(x)/x: x := 1.23: diff(f, x)
if f (x0 ) = g(x0 ) = · · · = f (k−1) (x0 ) = g (k−1) (x0 ) = 0 and g (k) (x0 ) ̸= 0. Compute
         x3 sin(x)
lim                  by applying this rule interactively. Use the function limit to
x→0 (1 − cos(x))2
check your result.
Exercise 7.3: Determine the first and second order partial derivatives of
f1 (x1 , x2 ) = sin(x1 x2 ) . Let x = x(t) = sin(t), y = y(t) = cos(t), and
f2 (x, y) = x2 y 2 . Compute the derivative of f2 (x(t), y(t)) with respect to t.
                                                                                                  7-3
7   Differentiation and Integration
    Integration
                          The function int features both definite and indefinite integration:
                           int(sin(x), x), int(sin(x), x = 0..PI/2)
                               − cos(x) , 1
                          While integrating, the integration variable itself is assumed to be real. Other than
                          this, all computations take place over the complex numbers, and the system
                          regards every symbolic parameter in the integrand as a complex number unless
                          told otherwise. In the following example, the definite integral exists only for
                          specific ranges of the parameter a, and the system returns a symbolic limit call:
                           int(sin(a*x)/x, x = 0..infinity)
                                lim Si(x a)
                               x→∞
                          You can tell the system that an identifier has certain properties by using the
                          operator assuming (Section 9.3). The following call stipulates that a be a positive
                          real number:
    7-4
                                                                             Integration
Besides the exact computation of definite integrals, MuPAD also provides several
numerical methods:
 float(int(sin(x)/x, x = 0..2))
    1.605412977
In the previous computation, int first returns a symbolic result (the error
function erf), which is then approximated by float. If you want to compute
numerically from the beginning, then you can suppress the symbolic computation
via int by using hold (Section 5.2):
 float(hold(int)(sin(x)/x, x = 0..2))
    1.605412977
Alternatively, the function numeric::int from the numeric library can be used:
 numeric::int(sin(x)/x, x = 0..2)
    1.605412977
This function allows you to choose different numerical methods for computing the
integral. You find more detailed information using ?numeric::int. It works in a
purely numerical fashion without any symbolic preprocessing of the integrand.
For smooth integrands without singularities, numeric::int is quite efficient.
                                                                                    7-5
7   Differentiation and Integration
                          Assist the system by using the substitution t = sin(x). Compare the value that you
                          get to the numerical result returned by the function numeric::int.
    7-6
                                                                       8
    Polynomial Equations
                         You can supply an individual equation as first argument to solve. The unknown
                         for which you want to solve is the second argument:
                          solve(x^2 + x = y/4, x), solve(x^2 + x - y/4 = 0, y)
                               { √        √        }
                                   y+1 1    y+1 1     {           }
                                −     − ,      −     , 4 x2 + 4 x
                                    2  2     2   2
                         In this case, the system returns a set of solutions. If you specify an expression
                         instead of an equation, then solve assumes the equation expression = 0:
                          solve(x^2 + x - y/4, y)
                               { 2      }
                                4x + 4x
                          solve(x^7 + x^2 + x, x)
                               {0} ∪ RootOf(z 6 + z + 1, z)
                         The above RootOf object represents all solutions of the equation x^6 + x + 1 = 0.
                         You can use float to approximate such objects by floating-point numbers. The
                         system internally employs a numerical procedure to determine all (complex) roots
                         of the polynomial:
                          float(%)
                               {0.0, 0.9454023333 - 0.6118366938 I,
- 0.7906671888 - 0.3005069203 I,
- 0.1547351445 - 1.038380754 I,
0.9454023333 + 0.6118366938 I,
- 0.7906671888 + 0.3005069203 I,
- 0.1547351445 + 1.038380754 I}
    8-2
                                                                     Polynomial Equations
If you solve equations for several variables, then MuPAD returns a set of “solved
equations” equivalent to the original system of equations. You can now read off
the solutions immediately: the unknown z has the value 1, the unknown y may be
arbitrary (indicated by the new indeterminate z1) and, for any given value of y , we
have x = 2 − y . It is possible to get a clearer indication of the new parameter not
present in the input by giving the option VectorFormat to the solve command:
 solve(equations, {x, y, z}, VectorFormat)
                    
                        
      x     2 − z1      
                
     y  ∈  z1  z1 ∈ C
           
                        
                          
      z        1    
You can use assign(solution[1]) to assign the solution values to the identifiers
x, y, and z.
                                                                                       8-3
8   Solving Equations: solve
                         MuPAD found two distinct solutions. Again, you can use | to substitute the
                         solutions in other expressions:
                          map(equations | solutions[1], expand),
                          map(equations | solutions[2], expand)
                               {1 = 1, 2 = 2} , {1 = 1, 2 = 2}
                                 {   +-                -+        |
                                 {   |     3            |        |
                                 {   | - z1 + 4 z1 + 4 |         |
                                 {   |                  |        |
                                 {   |       z1         |        |
                                 {   +-                -+        |
                                                                          }
                                                                          }
                                               4     3     2              }
                                 z1 in RootOf(z - 3 z - 2 z + 5 z + 8, z) }
                                                                          }
                                                                          }
    8-4
                                                                     Polynomial Equations
If you use the option MaxDegree = n, then RootOf expressions for polynomials of
degree up to n are replaced by representations in terms of radicals if this is
possible. Note that such solutions tend to be rather complicated:
 solve({x^3 + x^2 + 2*x = y, y^2 = x^3}, {x, y},
       MaxDegree = 4)
           √ (                 )1
   
   
                         √ √
                                          (         √ √        )2
   
                          3 73 5 i 3
               129 3485
                    54 +
   
                        18
                                      + 9   3485
                                                 +     3 73 5 i 3
                                                                  + 145
                       4                    54         18
    x = 7 +                                                           + ...
                           (          √ √       ) 1
   
                              3485      3 73 5 i 6
   
                           6     54  +      18
Specifying the unknowns to solve for is optional. For the special case where you
have one unknown, however, the format of the output depends on whether you
specify the unknown or not. The general rule is as follows:
                                                                                     8-5
8   Solving Equations: solve
                         If you do not supply unknowns to solve for, solve internally uses the system
                         function indets to find the symbolic identifiers in the equations and regards all of
                         them as unknowns:
                          solve({x + y^2 = 1, x^2 - y = 0})
                               (       )       {(             )                                }
                                                               
                                   x                1 − z12    
                                           ∈                    z1 ∈ RootOf(z − 2 z − z + 1, z)
                                                                              4     2
                                   y                  z1       
                         By default, solve tries to find all complex solutions of the given equation(s). If
                         you want to find only the real solutions of a single equation, use the option
                         Domain = Dom::Real or assume x to be real:
                          solve(x^3 + x = 0, x)
                               {0, −i, i}
                          solve(x^3 + x = 0, x) assuming x in R_
                               {0}
                         Other assumptions, such as x > 0, x in Q_, x in Z_ and x > 2, etc., are handled as well.
                         In some (usually exotic) cases, the “real solutions” may include unexpected values:
                          solve(ln(x)^4=PI^4, x) assuming x in R_
                               {             }
                                −1, e−π , eπ
                         When replacing the x in our input by −1, we get an ln(−1), which is π i, a complex
                         value. In the end, we get a real-valued result, but a common request is to find
                         solutions for a problem restricted to the reals, including all intermediate values
                         (“solving over the reals”). To make solve tackle this problem, use the option Real
                         instead of the assumption:
                          solve(ln(x)^4=PI^4, x, Real)
                               { −π π }
                                e ,e
    8-6
                                                                                  Polynomial Equations
If all complex numbers satisfy a given equation, then solve returns C, the set of
all complex numbers:
 solve(sin(x) = cos(x - PI/2), x)
     C
 domtype(%)
     solvelib::BasicSet
There are four such “basic sets”: the integers Z (entered as Z_ in MuPAD input),
the rational numbers Q (Q_), the real numbers R (R_), and the complex numbers C
(C_).
You can use the function float to find numerical solutions. However, with a
statement of the form float(solve(equations, unknowns)), solve first tries to
solve the equations symbolically. If an exact solution is found, float converts the
result to floating-point approximations. If you want to compute in a purely
numerical way, you can use hold (Section 5.2) to avoid symbolic preprocessing:
 float(hold(solve)({x^3 + x^2 + 2*x = y, y^2 = x^2},
                   {x, y}))
   {[x = - 0.5 + 1.658312395 I, y = 0.5 - 1.658312395 I],
[x = - 0.5 + 0.8660254038 I,
[x = - 0.5 - 0.8660254038 I,
], [x = 0.0, y = 0.0]}
                                                                                                  8-7
8   Solving Equations: solve
Exercise 8.1: Compute the general solution of the system of linear equations
                                             a   + b + c + d + e =               1,
                                             a   + 2b + 3c + 4d + 5e =           2,
                                             a   − 2b − 3c − 4d − 5e =           2,
                                             a   − b − c − d − e =               3.
    8-8
                                                                      General Equations and Inequalities
              The data type of the returned result is a so-called “image set.” It represents a
              mathematical set of the form {f (x) | x ∈ A}, where A is some other set:
               domtype(S)
                  Dom::ImageSet
                                                                                                       8-9
8   Solving Equations: solve
                         The equation exp(x) = sin(x) also has infinitely many solutions, which, however,
                         MuPAD® cannot represent exactly. In this case, it returns the call to solve
                         symbolically:
                          solutions := solve(exp(x) = sin(x), x)
                               solve(ex − sin(x) = 0, x)
                         However, you can specify a search range to select a particular numerical solution:
                          numeric::solve(exp(x) = sin(x), x = -10..-9)
                               {−9.424858654}
                         Using numeric::realroots, you can find enclosures for all real roots in a given
                         interval:
                          numeric::realroots(exp(x) = sin(x), x = -10..-5)
                               [[−9.43359375, −9.423828125] , [−6.2890625, −6.279296875]]
                         MuPAD has a special data type for the solution of parametric equations:
                         piecewise. For example, the set of solutions x ∈ C of the equation
                         (a x2 − 4) (x − b) = 0 takes on different forms, depending on the value of the
                         parameter a:
                          delete a: p := solve((a*x^2 - 4)*(x - b), x)
                               {
                                   {    {b}        } if a = 0
                                    b, − √2a , √2a   if a ̸= 0
                          domtype(p)
                               piecewise
    8-10
                                                        General Equations and Inequalities
The function solve can also handle inequalities. It then returns an interval or a
union of intervals, of domain type Dom::Interval or image sets, of domain type
Dom::ImageSet:
 solve(x^2 < 1, x)
    (−1, 1) ∪ { y i| y ∈ R}
 domtype(%)
    DOM_EXPR
 S := solve(x^2 >= 1, x)
    [1, ∞) ∪ (−∞, −1]
                                                                                     8-11
8   Solving Equations: solve
    Differential Equations
                         The function ode defines an ordinary differential equation. Such an object has two
                         components: an equation and the function to solve for.
                          diffEquation := ode(y'(x) = y(x)^2, y(x))
                                  (                      )
                               ode y ′ (x) − y(x) , y(x)
                                                 2
                         The following call to solve finds the general solution containing an arbitrary
                         constant C3 :
                          solve(diffEquation)
                               {                }
                                         1
                                0, −
                                       C3 + x
                         You can specify initial conditions or boundary values by passing the differential
                         equation together with the initial/boundary conditions as a set when calling ode:
                          diffEquation :=
                          ode({y''(x) = y(x), y(0) = 1, y'(0) = 0}, y(x)):
                         MuPAD now adjusts the free constants in the general solution according to the
                         initial/boundary conditions:
                          solve(diffEquation)
                               {               }
                                    1     ex
                                      x
                                        +
                                   2e      2
    8-12
                                                                         Differential Equations
You can specify systems of equations with several functions in form of a set:
 solve(ode({y'(x) = y(x) + 2*z(x), z'(x) = y(x)},
           {y(x), z(x)}))
     {[                                          ]}
              C12 e2 x  C11        C11
       z(x) =          − x , y(x) = x + C12 e 2x
                 2       e          e
in the form
 f := (x, Y) -> [Y[1] + 2*Y[2], Y[1]]:
Note that f (x, Y ) must be a vector. Here, this is realized by means of a list
containing the components on the right-hand side of the differential equation.
The call
 numeric::odesolve(0..1, f, [1, 1])
     [9.729448318, 5.04866388]
computed above by substituting the initial values y(0) = 1, z(0) = 1 in the general
symbolic solution, determining the values for the free constants, and evaluating
the symbolic solution at x = 1.
                                                                                          8-13
8   Solving Equations: solve
Exercise 8.3:
2) Determine the solution y(x) for each of the following initial value problems:
                                                   a)        y ′ − y sin(x) = 0 ,      y ′ (1) = 1,
                                                                        y
                                                        b)     2 y′ +     =0,       y ′ (1) = π .
                                                                        x
                           3) Find the general solution of the following system of ordinary differential
                              equations in x(t), y(t), z(t):
x′ = y z, y ′ = x z, z ′ = t z.
    8-14
                                                                                  Recurrence Equations
Recurrence Equations
             Recurrence equations are equations for functions depending on a discrete
             parameter (an “index”). You can generate such an object with the function rec,
             whose arguments are an equation, the function to be determined and, optionally,
             a set of initial conditions:
              equation := rec(y(n + 2) = y(n + 1) + 2*y(n), y(n)):
              solve(equation)
                        n
                 {(−1) C1 + 2n C2}
             The general solution contains two arbitrary constants (C1 , C2 in this case), which
             are suitably adjusted when you specify initial conditions:
              solve(rec(y(n + 2) = 2*y(n) + y(n + 1), y(n),
                        {y(0) = 1}))
                                n
                 {2n C4 − (−1) (C4 − 1)}
                                                                                                   8-15
                                                                      9
Manipulating Expressions
                                          i           i
                             sin(x) = −     exp(x i) + exp(−x i).
                                          2           2
                                                                                              
                                   collect    :   collecting coefficients
                                   combine    :   combining subexpressions
                                   expand     :   expansion
                                   factor     :   factorization
                                   normal     :   normalization of rational expressions
                                   partfrac   :   partial fraction decomposition
                                   radsimp    :   simplification of radicals
                                   rectform   :   Cartesian representation of complex values
                                   rewrite    :   applying mathematical identities
                                   simplify   :   universal simplifier
                                   Simplify   :   universal simplifier
                                                                                              
    9-2
                                                                                Transforming Expressions
Transforming Expressions
             If you enter the command collect(expression, unknown), the system regards
             the expression as a polynomial in the specified unknown and groups the
             coefficients of equal powers:
              x^2 + a*x + sqrt(2)*x + b*x^2 + sin(x) + a*sin(x):
              collect(%, x)
                              (   √ )
                  (b + 1) x2 + a + 2 x + (sin(x) + a sin(x))
              combine(sqrt(6)*sqrt(7)*sqrt(x))
                  √
                   42 x
                                                                                                    9-3
9   Manipulating Expressions
                         f := (PI^(1/2))^x: f = combine(f)
                               √ x   x
                                π = π2
                        If |xy| < 1, the inverse arctan of the tangent function satisfies the following
                        identity:
                         f := arctan(x) + arctan(y):
                         f = combine(f, arctan) assuming 0 < x*y < 1
                                                               (         )
                                                                x+y
                               arctan(x) + arctan(y) = − arctan
                                                                xy − 1
                        Note, however, that the identity exp(x)y = exp(x y) known to hold for real values
                        of x does not hold throughout the complex plane. Consequently, without
                        additional assumptions on x, MuPAD® does not combine such terms:
                         combine(exp(x)^y, exp)
                                        y
                               (ex )
                        With certain assumptions about x and y , the logarithm satisfies the rules
                        ln(x) + ln(y) = ln(x y) and x ln(y) = ln(y x ):
                         combine(ln(x) + ln(2) + 3*ln(3/2), ln)
                                    (          )
                                        27 x
                               ln
                                         4
    9-4
                                                                 Transforming Expressions
The trigonometric functions satisfy a variety of identities that the system employs
to combine products:
 combine(sin(x)*cos(y), sincos),
 combine(sin(x)^2, sincos)
     sin(x − y) sin(x + y) 1 cos(2 x)
               +          , −
         2          2      2    2
The function expand applies the identities used by combine in the reverse
direction: it transforms special function calls with composite arguments to sums
or products of function calls with simpler arguments via “addition theorems:”
 expand(x^(y + z)), expand(exp(x + y - z + 4)),
 expand(ln(2*PI*x*y))
              e 4 ex ey
    xy xz ,             , ln(2) + ln(π) + ln(x y)
                  ez
 expand(sin(x + y)), expand(cosh(x + y))
    cos(x) sin(y) + cos(y) sin(x) , cosh(x) cosh(y) + sinh(x) sinh(y)
 expand(sqrt(42*x*y))
    √ √
     42 x y
                                                                                      9-5
9   Manipulating Expressions
                        Here the system factors “over the rational numbers:” it looks for polynomial
                        factors with rational number
                                                   √coefficients.
                                                             √     In effect, MuPAD does not return the
                        factorization x2 − 2 = (x − 2) (x + 2):
                         factor(x^2 - 2)
                               ( 2   )
                                x −2
                        To extend the ring of constants over which to factor, you can explicitly adjoin
                        constants to the field of rational numbers:
                         factor(x^2 - 2, Adjoin = sqrt(2))
                               (        √ ) (  √ )
                                   x−    2 · x+ 2
                        MuPAD can factor not only polynomials and rational functions. For more general
                        expressions, the system internally replaces subexpressions such as symbolic
    9-6
                                                                 Transforming Expressions
The function normal computes a “normal form” for rational expressions. Like
factor, it first computes a common denominator for sums of rational expressions,
but it then expands numerator and denominator instead of factoring them:
 f := ((x + 6)^2 - 17)/(x - 1)/(x + 1) + 1:
 f, factor(f), normal(f)
              2                            2
      (x + 6) − 17          2 · (x + 3)       2 x2 + 12 x + 18
                     + 1,                   ,
     (x − 1) (x + 1)      (x − 1) · (x + 1)        x2 − 1
The denominators of the terms are the factors that MuPAD finds when factoring
                                                                                     9-7
9   Manipulating Expressions
partfrac(1/denominator, x)
                               250 − 250
                               9x     13
                                                   1           1             1
                                           −             −            +
                                x2 + 1         25 (x + 2) 25 (x + 2)2   250 (x − 3)
                                                        2 tan(x/2)                 1 − tan(x/2)2
                                           sin(x) =                 ,   cos(x) =                 .
                                                      1 + tan(x/2)2                1 + tan(x/2)2
The trigonometric functions are also related to the complex exponential function:
                                                                i           i
                                                   sin(x) = −     exp(i x) + exp(−i x) ,
                                                                2           2
                                                        1            1
                                                           exp(i x) + exp(−i x) .
                                                    cos(x) =
                                                        2            2
                        You can express the hyperbolic functions and their inverse functions in terms of
                        the exponential function and the logarithm:
    9-8
                                                              Transforming Expressions
                                                                       
    target      : function(s)                        → rewritten
                                                       in terms of
    andor       : logical operators xor, ==>, <=>    →   and, or, not
    arccos      : inverse trig. functions            →   arccos
    arccosh     : inverse trig. functions, ln        →   arccosh
    arccot      : inverse trig. functions            →   arccot
    arccoth     : inverse trig. functions, ln        →   arccoth
    arcsin      : inverse trig. functions            →   arcsin
    arcsinh     : inverse trig. functions, ln        →   arcsinh
    arctan      : inverse trig. functions            →   arctan
    arctanh     : inverse trig. functions, ln        →   arctanh
    bernoulli   : euler                              →   bernoulli
    cos         : exponential function exp,          →   cos
                  trig. and hyperbolic functions
    cosh        : exponential function exp,          → cosh
                  trig. and hyperbolic functions
    cot         : exponential function exp,          → cot
                  trig. and hyperbolic functions
    coth        : exponential function exp,          → coth
                  trig. and hyperbolic functions
    diff        : differential operator D            → diff
    D           : differentiating function diff      → D
    exp         : powers (^), trig. and hyperbolic   → exp, ln
                  functions and their inverses,
                  polar angle arg, dawson
    erf         : dawson                             → erf
    fact        : Γ-function gamma,                  → fact
                  double factorial fact2,
                  binomial coefficients binomial,
                  β -function beta, pochhammer
    gamma       : factorial fact,                    → gamma
                  double factorial fact2,
                  binomial coefficients binomial,
                  β -function beta, pochhammer
                                                                       
                                                                                  9-9
9   Manipulating Expressions
                                                                                                     
                                   target      : function(s)                          → rewritten
                                                                                        in terms of
                                   harmonic  : psi                                    →   harmonic
                                   heaviside : sign                                   →   heaviside
                                   Im        : Re                                     →   Im
                                   ln        : inverse trig. and inverse hyperbolic   →   ln
                                               functions, polar angle arg, log
                                   lambertW : wrightOmega                             →   lambertW
                                   max       : min, abs                               →   max
                                   min       : max, abs                               →   min
                                   piecewise : sign, absolute value abs,              →   piecewise
                                               step function heaviside,
                                               maximum max, minimum min,
                                                kroneckerDelta
                                   psi      : harmonic                                → psi
                                   Re       : Im                                      → Re
                                   sign     : step function heaviside,                → sign
                                              absolute value abs
                                   sin      : exponential function exp,               → sin
                                              trig. and hyperbolic functions
                                   sincos   : exponential function exp,               → sin, cos
                                              trig. and hyperbolic functions
                                   sinh     : exponential function exp,               → sinh
                                              trig. and hyperbolic functions
                                   sinhcosh : exponential function exp,               → sinh, cosh
                                              trig. and hyperbolic functions
                                   tan      : exponential function exp,               → tan
                                              trig. and hyperbolic functions
                                   tanh     : exponential function exp,               → tanh
                                              trig. and hyperbolic functions
                                                                                                     
    9-10
                                                                Transforming Expressions
For expressions representing complex numbers, you can easily compute real and
imaginary parts by using Re and Im:
 z := 2 + 3*I: Re(z), Im(z)
    2, 3
 z := sin(2*I) - ln(-1): Re(z), Im(z)
    0, sinh(2) − π
In such a case, you can use the function rectform (short for: rectangular form) to
decompose the expression into real and imaginary part. The name of this function
is derived from the fact that it computes the coordinates of the usual rectangular
(Cartesian) coordinate system. MuPAD decomposes the symbols contained in the
expression into their real and imaginary parts and expresses the final result
accordingly:
 rectform(a*b + I)
    ℜ(a) ℜ(b) − ℑ(a) ℑ(b) + ℑ(a) ℜ(b) i + ℑ(b) ℜ(a) i + i
rectform(exp(x))
                                                                                     9-11
9   Manipulating Expressions
                        Again, you can extract the real and imaginary parts of the result with Re and Im,
                        respectively:
                         Re(%), Im(%)
                        You can use the function expr to convert such an object to a “normal” expression
                        of domain type DOM_EXPR:
                         expr(z)
                               a ℑ(b) i + a ℜ(b) + i
    9-12
                                                                               Simplifying Expressions
Simplifying Expressions
              In some cases, a transformation leads to a simpler expression:
               f := 2^x*3^x/8^x/9^x: f = combine(f)
                             (        )x
                   2x 3x         1
                         =
                   8x 9x         12
              To this end, however, you must inspect the expression and decide yourself which
              function to use for simplification. There are tools for applying various
              simplification algorithms to an expression automatically: the functions simplify
              and Simplify. These are universal simplifiers which MuPAD® uses to achieve a
              representation of an expression that is as “simple” as possible:
               f := 2^x*3^x/8^x/9^x: f = simplify(f)
                   2x 3x    1
                    x  x
                         = 2x x
                   8 9    2 3
               f := (1 + (sin(x)^2 + cos(x)^2)^2)/sin(x):
               f = simplify(f)
                   (                           )2
                             2             2
                       cos(x) + sin(x)              +1          2
                                                         =
                                 sin(x)                      sin(x)
                                                                                                 9-13
9   Manipulating Expressions
                        Note that simplify operates in a purely heuristic way since there is no general
                        answer what “simple” means. You can control the simplification process by
                        supplying additional arguments. As in the case of combine, you can request
                        particular simplifications by means of options. For example, you can tell the
                        simplifier explicitly to simplify expressions containing square roots:
                         f := sqrt(4 + 2*sqrt(3)):
                         f = simplify(f, sqrt)
                                    √
                               √     √          √
                                2        3+2=    3+1
                        The possible options are exp, ln, log, cos, sin, cosh, sinh, sqrt, gamma, unit,
                        condition, logic, and relation. Internally, simplify then confines itself to
                        those simplification rules that are valid for the function given as option. The
                        options logic and relation are for simplifying logical expressions and equations
                        and inequalities, respectively (see also the corresponding help page: ?simplify).
                        Instead of simplify(expression, sqrt), you may also use the function radsimp
                        to simplify numerical expressions containing square roots or other radicals:
                         f = radsimp(f)
                                    √
                               √     √          √
                                2        3+2=    3+1
    9-14
                                                                              Simplifying Expressions
The second general simplifier, Simplify (note the capital S), is often slower than
simplify, but much more powerful and allows much finer tuning:
 Simplify(1/(x+y) + 1/(x-y)),
 Simplify(1/(x+y) + 1/(x-y), Valuation=length)
       2x       1     1
             ,     +
     x2 − y 2 x − y x + y
 g := gamma(n + n!/gamma(n+1)):
 g, simplify(g), Simplify(g)
     (                     )         (                      )
                   n!                    n! + n Γ (n + 1)
    Γ n+                       , Γ                              , Γ (n + 1)
               Γ (n + 1)                    Γ (n + 1)
 assume(n, Type::PosInt):
 f := (1 + I)^n + (1 - I)^n:
 Simplify(f), Simplify(f, Steps = 350)
                                     n
                                            (π n)
           n           n
    (1 − i) + (1 + i) , 2 2 2 cos
                                               4
Here, we have used the option Steps to tell Simplify how many “elementary”
steps it may try before giving up the search for a simpler expression. In the end,
almost all of the steps have led nowhere; we can ask Simplify for a list of steps it
performed and see that only four steps were actually used:
                                                                                                9-15
9   Manipulating Expressions
                               substituting gives
                                 2^(n/2)*exp(-(PI*n*I)/4) + ((1 + I))^n
                               Lemma:
                               ((1 + I))^n = 2^(n/2)*exp((PI*n*I)/4)
                               Input was
                                 ((1 + I))^n
                               Applying the rule
                                 #X -> abs(op(#X, 1))^op(#X, 2)*exp(I*op(#X, 2)*arg(\
                               op(#X, 1)))
                               gives
                                 2^(n/2)*exp((PI*n*I)/4)
                               End of lemma
                               substituting gives
                                 2^(n/2)*exp(-(PI*n*I)/4) + 2^(n/2)*exp((PI*n*I)/4)
                               Applying the rule
                                 Simplify::rewriteTrig
                               gives
                                 2*exp((n*ln(2))/2)*cos((PI*n)/4)
                               Applying the rule
                                 Simplify::expand
                               gives
                                 2*2^(n/2)*cos((PI*n)/4)
                               END OF PROOF
    9-16
                                                                       Simplifying Expressions
As we have seen above in the first example, the user can also control Simplify’s
idea of what is “simple.” Exercise 9.4 shows an application.
holds.
                                                                                         9-17
9   Manipulating Expressions
                         diff(%, x)
                                                                                                           √
                               sin(x) − 1      √             2 sin(x) (sin(x) − 1)                          sin(x) + 1
                               √            + 2 sin(x) + 1 +                      2
                                 sin(x) + 1                                cos(x)
                        Exercise 9.4: Using the option Valuation, we may pass a function to Simplify
                        to determine which expressions are “simple:” the function is called with an
                        expression as its argument and returns a number, higher numbers for more
                        complex expressions.
                        Let us try to write tan(x) − cot(x) without the tangent and cotangent functions.
                        The first, somewhat naive approach is to use a valuation function that simply
                        looks for the presence of tan and cot:2
                         noTangent := x -> if has(x, [hold(tan), hold(cot)])
                                           then 10
                                           else 1 end_if:
                         Simplify(tan(x) - cot(x), Valuation = noTangent)
                                   (                          )                      (        )2
                                       e−x i i       ex i i                              e−x i
                                                                                           xi
                               2         2       −    2                          2      + e2
                                                                                          2
                                                                  −(                    )(             )
                                   e−x i + ex i                        e−x i i      xi
                                                                                 − e2 i   e−x i + ex i
                                                                         2
                        Now, this expression actually does not contain tan, but is hardly “simple.”
                        Improve noTangent such that the call above returns a simple expression without
                        tan and cot. You might want to inform yourself about length first or use
                        Simplify::defaultValuation instead, which is the function used by Simplify if
                        nothing is specified.
    9-18
                                                              Assumptions about Mathematical Properties
             You can use the function assume to tell the system functions such as expand,
             simplify, limit, solve, and int that they may make certain assumptions about
             the meaning of certain expressions. We only demonstrate some simple examples
             here. You find more information on the corresponding help page: ?assume.
             You can use an expression such as an inequality or containment in a set, including
             the basic sets of the solver (cf. page 8-7) to tell MuPAD that a symbolic identifier
             or expression represents only values corresponding to the mathematical meaning
             of the type. For example, the commands
              assume(x in R_): assume(y in R_): assume(n in Z_):
             The command
              assume(x > 0):
                                                                                                    9-19
9   Manipulating Expressions
                        Here, the Boolean value UNKNOWN expresses the fact that the system cannot decide
                        whether x represents an integer or not.
    9-20
                                               Assumptions about Mathematical Properties
In contrast to is, the function testtype presented in Section 14.1 checks the
technical type of a MuPAD object:
 testtype(x, Type::Integer), testtype(x, DOM_IDENT)
    FALSE, TRUE
 limit(exp(a*x), x=infinity);
 limit(exp(a*x), x=infinity) assuming a < 0
    
    
            1          if a = 0
    
    
    
            ∞           if 0 < a
    
           0           if ℜ(a) < 0
    
    
    
        limx→∞ e   ax
                        if ℜ(a) = 0 ∧ a ̸= 0 ∨ 0 < ℜ(a) ∧ ¬0 < a
You can delete the properties of an identifier using unassume or the keyword
delete:
 delete y: is(y > 5)
    UNKNOWN
                                                                                   9-21
9   Manipulating Expressions
                         getprop(3), getprop(sqrt(2) + 1)
                                       {√    }
                               {3} ,     2+1
                        Assuming some property deletes all previous assumptions using the same
                        identifiers:
                         assume(sin(x) > y):
                         getprop(y)
                               (−∞, sin(x))
    9-22
                                               Assumptions about Mathematical Properties
We now illustrate some of the various types of properties with a short example.
The equation (xa )b = xab is not generally valid, as the example x = −1, a = 2, and
b = 1/2 shows. However, it is valid if b is an integer:
 assume(b in Z_): (x^a)^b
    xa b
 unassume(b): (x^a)^b
              b
    (xa )
 linalg::isPosDef(A)
   Error: cannot check whether matrix component is positive
   [linalg::factorCholesky]
With the additional assumption that the parameter a be positive and less than 1,
MuPAD can decide that the matrix is positive definite:
 assume(a, Type::Interval(0, 1))
 linalg::isPosDef(A)
    TRUE
Properties of this type can be specified in the following more intuitive way as well:
 assume(0 < a < 1)
                                                                                        9-23
9   Manipulating Expressions
                         simplify(%)
                               −1
                        The property above can also be specified in any of the following equivalent forms:
                         assume(k in 4*Z_ + 3)
                         assume((k - 3)/4 in Z_)
                        The functions Re, Im, sign, and abs take properties into account:
                         assume(x > 1):
                         Re(x*(x - 1)), sign(x*(x - 1)), abs(x*(x - 1))
                               x (x − 1) , 1, x (x − 1)
                        Since only a limited number of mathematical properties and derivation rules are
                        implemented in MuPAD, the system performs some simplifications when
                        evaluating the properties of a nontrivial expression. Thus the answer of getprop
                        or is is sometimes not “as close as possible.” For example, if x is a real number,
                        then x2 − x ≥ −1/4, but getprop yields the following less accurate answer:
                         assume(x, Type::Real): getprop(x^2 - x)
                               R
    9-24
                                                                                   10
      You can use MuPAD® ’s random number generators random, frandom and
      stats::xxxRandom to perform many experiments.
      The call random() generates a random nonnegative 12 digit integer. You obtain a
      sequence of 4 such random numbers as follows:
       random(), random(), random(), random()
           427419669081, 321110693270, 343633073697, 474256143563
      If you want to generate random integers in a different range, you can construct a
      random number generator generator:= random(m..n). You call this generator
      without arguments,1 and it returns integers between m and n. The call random(n)
      is equivalent to random(0..n-1). Thus you can simulate 15 rolls of a die as
      follows:
       die := random(1..6):
       dieExperiment := [die() $ i = 1..15]
           [5, 3, 6, 3, 2, 2, 2, 4, 4, 3, 3, 2, 1, 4, 4]
      We stress that you must specify a loop variable when using the sequence generator
      $, since otherwise die() is called only once and a sequence of copies of this value
      is generated:
       die() $ 15
           6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
1 In fact, you can call generator with arbitrary arguments, which are ignored when generating ran-
      dom numbers.
10   Chance and Probability
0.6818588132]
                         The library stats comprises functions for statistical analysis. You obtain
                         information by entering info(stats) or ?stats. For example, the function
                                                                      1
                                                                         ∑n
                         stats::mean computes the mean value X = n          i=1 xi of a list of numbers
                         [x1 , . . . , xn ]:
                          stats::mean(dieExperiment),
                          stats::mean(coinTosses),
                          stats::mean(randomNumbers)
                               16 3
                                 , , 0.4863510522
                               5 8
                                                                    1 ∑
                                                                         n
                                                         V ar =             (xi − X)2 :
                                                                  n − 1 i=1
     10-2
                                                                                     Chance and Probability
 stats::variance(dieExperiment),
 stats::variance(coinTosses),
 stats::variance(randomNumbers)
     61 15
       ,   , 0.08565360412
     35 56
                                                    √
You can compute the standard deviation               V ar with stats::stdev:
 stats::stdev(dieExperiment),
 stats::stdev(coinTosses),
 stats::stdev(randomNumbers)
     √ √      √ √
      35 61    14 15
            ,        , 0.29266637
       35       28
                                                                         √
                                                                             n−1
If you specify the option Population, the system returns                      n    V ar instead:
 stats::stdev(dieExperiment, Population),
 stats::stdev(coinTosses, Population),
 stats::stdev(randomNumbers, Population)
     √ √      √
      3 122     15
            ,      , 0.2776476971
       15      8
If you simulate 1000 rolls of a die, you might obtain the following frequencies:
 rolls := die() $ i = 1..1000:
 Dom::Multiset(rolls)
     {[1, 158] , [2, 152] , [3, 164] , [4, 188] , [5, 176] , [6, 162]}
In this case, you would have rolled 158 times a 1, 152 times a 2 etc.
                                                                                                      10-3
10   Chance and Probability
                         The result becomes much more readable if we sort it by the first entry of the
                         sublists. We employ the function sort which takes a function representing a
                         sorting order as second argument. This function decides which of two elements
                         x, y shall precede the other. We refer to the corresponding help page: ?sort. In
                         this case, x, y are lists with two entries, and we want x to appear before y if we
                         have x[1] < y[1] (i.e., we sort numerically with respect to the first entries):
                          sortingOrder := (x, y) -> (x[1] < y[1]):
                          sort([op(frequencies)], sortingOrder)
                              [[1, 596], [2, 142], [3, 84], ..., [212, 1], [377, 1]]
                         In this experiment, 596 out of the 1000 chosen random pairs have a gcd of 1 and
                         hence are coprime. Thus, we found 59.6% as an approximation of the probability
                         that two randomly chosen integers are coprime. The theoretical value of this
                         probability is 6/π 2 ≈ 0.6079.. =
                                                         b 60.79%.
                         The stats library provides many stochastic distribution functions. Each such
                         distribution xxx, say, consists of four functions: a cumulative distribution
                         function xxxCDF, a probability density function xxxPDF (or a discrete probability
                         function xxxPF, respectively), a quantile function xxxQuantile, and a random
                         number generator xxxRandom. For example, the following command creates a list
                         of random numbers distributed according to the standard normal distribution
                         with mean 0 and variance 1:
     10-4
                                                                     Chance and Probability
The χ2 -test requires to specify a “cell partitioning” of the real line to compare the
observed frequencies of the data falling into the cells with the expected
frequencies given a hypothesized distribution of the data. The function
stats::equiprobableCells is a convenient utility function to compute a cell
partitioning consisting of cells that are equiprobable with respect to a given
distribution. The following call partitions the real line into 32 cells which are
equiprobable with respect to the normal distribution with the empirical mean and
variance computed above:
 cells := stats::equiprobableCells(32,
                    stats::normalQuantile(m, V))
   [[-infinity, -1.89096853], [-1.89096853, -1.553118836],
MinimalExpectedCellFrequency = 31.25]
The first value returned by stats::csGOFT is the significance level attained by the
data. Since this value is not small, the given data pass the test well.
                                                                                         10-5
10   Chance and Probability
                         We check whether the new data still may be regarded as a normally distributed
                         sample:
                          m := stats::mean(data): V := stats::variance(data):
                          cells := stats::equiprobableCells(32,
                                              stats::normalQuantile(m, V)):
                          stats::csGOFT(data, cells,
                                        CDF = stats::normalCDF(m, V))
                              [PValue = 0.000004764116336, StatValue = 78.87826087,
MinimalExpectedCellFrequency = 32.34375]
                         Now, the attained significance level 0.0010... indicates that the hypothesis of a
                         normal distribution of the data must be rejected at significance levels as low as
                         0.001.
                         See the help page of stats::csGOFT for further details.
                         Exercise 10.1: Three dice are thrown simultaneously. For each value between 3
                         and 18, the following table contains the expected frequencies of the total dice
                         score when rolling the dice 216 times:
                                                                score
                                   3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
                                   1 3 6 10 15 21 25 27 27 25 21 15 10 6 3 1
                                                              frequency
                         Simulate 216 rolls and compare the frequencies that you observe with those from
                         the table.
                         Exercise 10.2: The Monte-Carlo method for approximating the area of a region
                         A ⊂ R2 works as follows. First, we choose a (preferably small) rectangle Q
                         enclosing A. Then we randomly choose n points in Q. If m of these points lie in A,
                         the following estimate holds for sufficiently large n:
                                                                  m
                                                    area of A ≈      × area of Q.
                                                                   n
     10-6
                                                                    Chance and Probability
  a) Consider the right upper quadrant of the unit circle around the origin. Use
     Monte-Carlo simulation with Q = [0, 1] × [0, 1] to approximate its area. This
     way, one gets stochastic approximations of π .
                                                                                        10-7
                                                                               11
Graphics
Introduction
               Since exploring mathematical objects is probably one of the most important uses
               of computer algebra systems, graphics are a rather central part of modern CAS.
               The MuPAD® system allows to easily create two- and three-dimensional graphics
               and animations with high quality output and advanced interactive manipulation
               capabilities.
               To aid the user in fine-tuning a plot, an object browser is provided. It allows to
               inspect and analyze the tree structure of graphical scenes interactively, giving easy
               access to all parts of the plot by a mouse-click. After selecting an object, all plot
               attributes such as color, line width, annotations etc. associated with the object
               become visible. One may select the attributes with the mouse and change their
               values interactively (see page 11-50). Thus, almost any detail of a plot generated
               by a MuPAD call can be changed interactively making it possible to fine-tune both
               the contents as well as the looks by visual inspection.
               The features of the renderer are fully supported by the plot library. It provides a
               list of graphical primitives such as points, lines, polygons etc. that one may use to
               build up highly complex graphical scenes. The primitives also include graphical
               objects that are not at all “primitive,” but come along with advanced algorithms
               and much built-in intelligence. Examples are function graphs in 2D and 3D (with
               automatic clipping for singular functions), implicit plots in 2D and 3D, vector field
               plots, graphical solutions of ordinary differential equations in 2D and 3D etc.
               This chapter gives an introduction to the new graphics system. It explains the
               basic concepts and ideas and provides many examples.
11   Graphics
2D Function Graphs
                   If several functions are to be plotted in the same graphical scene, just pass a
                   sequence of function expressions. All functions are plotted over the specified
                   common range:
     11-2
                                                      Easy Plotting: Graphs of Functions
To get a legend explaining the mapping from color to function, add the option
LegendVisible:
                                                                                   11-3
11   Graphics
                The name x used in the specification of the plotting range provides the name that
                labels the horizontal axis.
     11-4
                                                        Easy Plotting: Graphs of Functions
Note that there are gaps in the definition of the function above: no function value
is specified for x = 1 and x = 2. This does not cause any problem, because plot
simply ignores all points that do not produce real numerical values. Thus, in the
following example, the plot is automatically restricted to the regions where the
functions produce real values:
                                                                                      11-5
11   Graphics
     11-6
                                                       Easy Plotting: Graphs of Functions
When several functions are plotted in the same scene, they are drawn in different
colors that are chosen automatically. With the Colors attribute one may specify a
list of RGB colors that plot shall use:
 plot(x, x^2, x^3, x^4, x^5, x = 0..1,
      Colors = [RGB::Red, RGB::Orange, RGB::Yellow,
                RGB::BlueLight, RGB::Blue],
      LegendVisible)
                                                                                    11-7
11   Graphics
     11-8
                                                           Easy Plotting: Graphs of Functions
Once the plot is created, the first frame of the picture appears as a static plot.
After double-clicking on the picture, the graphics tool allows to start the
animation by pushing the “Start” button:
                                                                                        11-9
11   Graphics
                An animation consists of separate frames, i.e., individual still images. The default
                number of frames is 50. If a different value is desired, just pass the attribute
                Frames = n, where n is the number of frames that shall be created:
                Apart from the color specification or the Frames number, there is a large number
                of further attributes that may be passed to plot. Each attribute is passed as an
                equation AttributeName = AttributeValue. Here, we only present some selected
                attributes. Section “Attributes for plotfunc2d and plotfunc3d” of the online plot
                documentation provides further tables with more attributes.
                                                                                                
                 attribute name           possible values           meaning                  default
                 Height                    8*unit::cm               physical height           80*unit::mm
                                                                    of the picture
                 Width                    12*unit::cm               physical width           120*unit::mm
                                                                    of the picture
                 Footer                   string                    footer text              "" (no footer)
                 Header                   string                    header text              "" (no header)
                 Title                    string                    title text               "" (no title)
                 TitlePosition            [real value,              coordinates of the
                                          real value]               lower left corner of
                                                                    the title
                                                                                                             
                                  Table 11.1: Some important attributes for plotting 2D functions
     11-10
                                                                    Easy Plotting: Graphs of Functions
                                                                                                    
 attribute name           possible values           meaning                  default
                                                                                                     11-11
11   Graphics
                First, we will give an example where the number of evaluation points needs
                adjustment. The following plot example features the notorious function sin(1/x)
                that oscillates wildly near the origin:
                 plot(sin(1/x), x = -0.5..0.5)
                Clearly, the default of 121 sample points used by plot does not suffice to create a
                sufficiently resolved plot.
     11-12
                                                      Easy Plotting: Graphs of Functions
We increase the number of numerical mesh points via the Mesh attribute.
Additionally, we increase the resolution depth of the adaptive plotting mechanism
from its default value AdaptiveMesh = 2 to AdaptiveMesh = 4:
 plot(sin(1/x), x = -0.5..0.5, Mesh = 500,
      AdaptiveMesh = 4)
                                                                                    11-13
11   Graphics
                The following call specifies a header via Header = "The function sin(x^2)".
                The distance between labeled ticks is set to 0.5 along the x axis and to 0.2 along the
                y axis via XTicksDistance = 0.5 and YTicksDistance = 0.2, respectively. Four
                additional unlabeled ticks between each pair of labeled ticks are set in the x
                direction via XTicksBetween = 4. One additional unlabeled tick between each pair
                of labeled ticks in the y direction is requested via YTicksBetween = 1. Grid lines
                attached to the ticks are “switched on” by GridVisible = TRUE and
                SubgridVisible = TRUE:
                 plot(sin(x^2), x = 0..7,
                      Header = "The function sin(x^2)",
                      XTicksDistance = 0.5, YTicksDistance = 0.2,
                      XTicksBetween = 4, YTicksBetween = 1,
                      GridVisible = TRUE, SubgridVisible = TRUE)
     11-14
                                                        Easy Plotting: Graphs of Functions
When singularities are found in the function, an automatic clipping is called trying
to restrict the vertical viewing range in some way to obtain a “reasonably” scaled
picture. This is a heuristic approach that sometimes needs a helping adaption “by
hand.” In the following example, the automatically chosen range between y ≈ −40
and y ≈ 260 in vertical direction is suitable to represent the 6th order pole at
x = 1, but it does not provide a good resolution of the first order pole at x = −1:
 plot(1/(x + 1)/(x - 1)^6, x = -2..2)
There is no good viewing range that is adequate for both poles because they are of
different order. However, some compromise can be found.
                                                                                       11-15
11   Graphics
                We override the automatic viewing range suggested by plot and request a specific
                viewing range in vertical direction via ViewingBoxYRange:
                 plot(1/(x + 1)/(x - 1)^6, x = -2..2,
                      ViewingBoxYRange = -10..10)
     11-16
                                                         Easy Plotting: Graphs of Functions
The values of the following function have a lower bound, but no upper bound. We
use the attribute ViewingBoxYRange = Automatic..10 to let plot find a lower
bound for the viewing box by itself whilst requesting a specific value of 10 for the
upper bound:
 plot(exp(x)*sin(PI*x) + 1/(x + 1)^2/(x - 1)^4,
      x = -2..2, ViewingBoxYRange = Automatic..10)
                                                                                       11-17
11   Graphics
3D Function Graphs
     11-18
                                                         Easy Plotting: Graphs of Functions
If several functions are to be plotted in the same graphical scene, just pass a
sequence of function expressions; all functions are plotted over the specified
common range:
 plot((x^2 + y^2)/4, sin(x - y)/(x - y),
      x = -2..2, y = -2..2, #3D)
                                                                                     11-19
11   Graphics
                The names x, y used in the specification of the plotting range provide the labels of
                the corresponding axes.
     11-20
                                                         Easy Plotting: Graphs of Functions
Note that there are gaps in the definition of the function above: no function value
is specified for x = y . This does not cause any problem, because plot simply
ignores points that do not produce real numerical values if it finds suitable values
in the neighborhood. Thus, missing points or singularities do not raise an error.
                                                                                       11-21
11   Graphics
     11-22
                                                       Easy Plotting: Graphs of Functions
When several functions are plotted in the same scene, they are drawn in different
colors that are chosen automatically. With the Colors attribute one may specify a
list of RGB colors that plot shall use:
 plot(2 + x^2 + y^2, 1 + x^4 + y^4, x^6 + y^6,
      x = -1..1, y = -1..1, #3D,
      Colors = [RGB::Red, RGB::Green, RGB::Blue])
                                                                                    11-23
11   Graphics
                Once the plot is created, the first frame of the picture appears as a static plot.
                After double-clicking on the picture, the graphics tool allows to start the
                animation by pushing the “Start” button.
     11-24
                                                                    Easy Plotting: Graphs of Functions
Apart from the color specification or the Frames number, there is a large number
of further attributes that may be passed to plot. Each attribute is passed as an
equation to plot. Here, we only present some selected attributes. Section
“Attributes for plotfunc2d and plotfunc3d” of the online plot documentation
provides further tables with more attributes.
                                                                                
 attribute name           possible values           meaning                  default
 Height                    8*unit::cm               physical height of the    80*unit::mm
                                                    picture
 Width                    12*unit::cm               physical width of the    120*unit::mm
                                                    picture
 Footer                   string                    footer text              "" (no footer)
 Header                   string                    header text              "" (no header)
 Title                    string                    title text               "" (no title)
 TitlePosition            [real value,              coordinates of the
                          real value]               lower left corner of
                                                    the title
 GridVisible              TRUE, FALSE               visibility of “major”    FALSE
                                                    grid lines
                                                                                              
                  Table 11.2: Some important attributes for plotting 3D functions
                                                                                                11-25
11   Graphics
                                                                                                                    
                 attribute name           possible values           meaning                  default
                Let us present some example uses of these attributes. As for 2D plots, we’ll start
                with the evaluation density.
     11-26
                                                      Easy Plotting: Graphs of Functions
In the following example, the default mesh of 25 × 25 sample points used by plot
does not suffice to create a sufficiently resolved plot:
 plot(sin(x^2 + y^2), x = -3..3, y = -3..3, #3D)
                                                                                   11-27
11   Graphics
                We increase the number of numerical mesh points via the Submesh attribute:
                 plot(sin(x^2 + y^2), x = -3..3, y = -3..3,
                      Submesh = [3, 3], #3D)
     11-28
                                                     Easy Plotting: Graphs of Functions
The following call specifies a header via Header = "The function sin(x - y^2)".
Grid lines attached to the ticks are “switched on” by GridVisible and
SubgridVisible:
                                                                                  11-29
11   Graphics
                There is no good viewing range that is adequate for both poles because they are of
                different order.
     11-30
                                                      Easy Plotting: Graphs of Functions
We override the automatic viewing range suggested by plot and request a specific
viewing range in the vertical direction via ViewingBoxZRange:
 plot(1/((x+1)^2 + (y-1)^2)/((x-1)^2 + (y-1)^2)^5,
      x = -2..3, y = -2..3, Submesh = [3, 3],
      ViewingBoxZRange = 0..0.1, #3D)
                                                                                   11-31
11   Graphics
                The values of the following function have a lower bound but no upper bound. We
                use the attribute ViewingBoxZRange = Automatic..20 to let plot find a lower
                bound for the viewing box by itself whilst requesting a specific value of 20 for the
                upper bound:
                 plot(1/x^2/y^2 + exp(-x)*sin(PI*y),
                      x = -2..2, y = -2..2, #3D,
                      ViewingBoxZRange = Automatic..20)
     11-32
                                                         Advanced Plotting: Principles and First Examples
General Principles
                                                                                                    11-33
11   Graphics
     11-34
                                           Advanced Plotting: Principles and First Examples
Alternatively, the generated objects allow to set attributes via slot assignments of
the form object::AttributeName:= AttributeValue as in
 p::Color := RGB::Black:
 p::PointSize := 4.0*unit::mm:
 t::Color := RGB::Red:
 t::LineWidth := 1.0*unit::mm:
The help page of each primitive provides a list of all attributes the primitive is
reacting to.
                                                                                       11-35
11   Graphics
                Certain attributes, such as axes style, the visibility of grid lines in the background
                etc. are associated with the whole scene rather than with the individual primitives.
                These attributes may be included in the plot call:
                 plot(g, t, p, GridVisible = TRUE)
                As explained in detail in Section “The Full Picture” on page 11-46, the plot
                command automatically embeds the graphical primitives in a coordinate system,
                which in turn is embedded in a graphical scene, which is drawn inside a canvas.
                The various attributes associated with the general appearance of the whole picture
                are associated with these “grouping structures.” A concise list of all such
                attributes is provided on the help pages of the corresponding primitives:
                plot::Canvas, plot::Scene2d, plot::Scene3d, plot::CoordinateSystem2d, and
                plot::CoordinateSystem3d, respectively.
                The MuPAD® object browser allows to select each primitive in the plot. After
                selection, the attributes of the primitive can be changed interactively in the
                property inspector (see page 11-50).
                Next, we wish to demonstrate an animation. It is remarkably simple to generate
                an animated picture. Going back to our previous example with the tangent to the
                function graph, we want to let the point x0 at which the tangent is added move
                along the graph of the function. In MuPAD, you do not need to create an
                animation frame by frame. Instead, each primitive can be told to animate itself by
     11-36
                                           Advanced Plotting: Principles and First Examples
Details on animations and further examples are provided starting on page 11-71.
                                                                                         11-37
11   Graphics
                       • Animations are not created frame by frame but per object (see also
                         Section 11.9). An object is animated by generating it with a symbolic
                         animation parameter and providing a range for this parameter in
                         the generating call. The section starting on page 11-71 provides fur-
                         ther details on animations.
                                                                                                  
     11-38
                                              Advanced Plotting: Principles and First Examples
Some Examples
The plot shall consist of the function f (x) that provides the data of the sample
points and of the spline interpolant S(x). The graphs of f (x) and S(x) are
generated via plot::Function2d. The data points are plotted as a
plot::PointList2d:
                                                                                              11-39
11   Graphics
     11-40
                                           Advanced Plotting: Principles and First Examples
Example 2: A cycloid is the curve that you get when following a point fixed to a
wheel rolling along a straight line. We visualize this construction by an animation
in which we use the x coordinate of the hub as the animation parameter. The
wheel is realized as a circle. There are 3 points fixed to the wheel: a green point on
the rim, a red point inside the wheel and a blue point outside the wheel:
 WheelRadius := 1:
 r := [1.5*WheelRadius, 1.0*WheelRadius, 0.5*WheelRadius]:
 WheelCenter := [x, WheelRadius]:
 WheelRim := plot::Circle2d(WheelRadius, WheelCenter,
                            x = 0..4*PI,
                            LineColor = RGB::Black):
 WheelHub := plot::Point2d(WheelCenter, x = 0..4*PI,
                           PointColor = RGB::Black):
 WheelSpoke := plot::Line2d(WheelCenter,
    [WheelCenter[1] + max(r)*sin(x),
     WheelCenter[2] + max(r)*cos(x)],
    x = 0..4*PI, LineColor = RGB::Black):
 color:= [RGB::Red, RGB::Green, RGB::Blue]:
 for i from 1 to 3 do
  Point[i] := plot::Point2d([WheelCenter[1] + r[i]*sin(x),
                             WheelCenter[2] + r[i]*cos(x)],
                             x = 0..4*PI,
                            PointColor = color[i],
                            PointSize = 2.0*unit::mm):
  Cycloid[i] := plot::Curve2d([y + r[i]*sin(y),
                               WheelRadius + r[i]*cos(y)],
                              y = 0..x, x = 0..4*PI,
                              LineColor = color[i]):
 end_for:
                                                                                         11-41
11   Graphics
     11-42
                                           Advanced Plotting: Principles and First Examples
                                                                                        11-43
11   Graphics
                  x 0.00 0.10 0.20 0.30 0.40 0.50 0.60 0.70 0.80 0.90 0.95 1.00
                 r(x) 0.60 0.58 0.55 0.51 0.46 0.40 0.30 0.15 0.23 0.24 0.20 0.00
     11-44
                                 Advanced Plotting: Principles and First Examples
plot(
  plot::XRotate(r(x), x = 0..1,
                AngleRange = 0.6*PI..2.4*PI,
                Color = RGB::MuPADGold),
  plot::Curve3d([x, 0, r(x)], x = 0..1,
                LineWidth = 0.5*unit::mm,
                Color = RGB::Black),
  plot::PointList3d([[p[1], 0, p[2]] $ p in samplepoints],
                    PointSize = 2.0*unit::mm,
                    Color = RGB::Red),
  CameraDirection = [70, -70, 40])
                                                                           11-45
11   Graphics
     11-46
                                                        The Full Picture: Graphical Trees
 plot(plot::Canvas(
   S1, S2, S3, S4,
   Width = 80*unit::mm, Height = 80*unit::mm,
   Axes = None, BorderWidth = 0.5*unit::mm,
   plot::Scene3d::BorderWidth = 0.5*unit::mm))
See Section “Layout of Canvas and Scenes” of the online plot documentation for
details on how the layout of a canvas containing several scenes is set.
Coordinate systems exist inside a 2D scene or a 3D scene and are of type
plot::CoordinateSystem2d or plot::CoordinateSystem3d, respectively. There
may be one or more coordinate systems in a scene. Inside the coordinate systems,
an arbitrary number of primitives (of the appropriate dimension) can be
displayed. Thus, we always have a canvas, containing one or more scenes, with
each scene containing one or more coordinate systems. The graphical primitives
(or groups of such primitives) are contained in the coordinate systems.
                                                                                   11-47
11   Graphics
     11-48
                                                           The Full Picture: Graphical Trees
                                                                                     11-49
11   Graphics
     11-50
                                  Viewer, Browser, and Inspector: Interactive Manipulation
After selection of an attribute with the mouse, its value can be changed:
There is a sophisticated way of setting defaults (see Section 11.7 and Section 11.7
for an explanation) for the attributes via the object browser and the property
inspector. The ‘View’ menu provides an item ‘Hide Defaults.’ Disabling ‘Hide
Defaults,’ the object browser shows entries for defaults:
                                                                                      11-51
11   Graphics
                At each node of the graphical tree, default values for the inheritable attributes can
                be set via the property inspector. These defaults are valid for all primitives that
                exist below this node, unless these defaults are re-defined at some other node
                further down in the tree hierarchy.
                This mechanism is particularly useful when there are many primitives of the same
                kind in the plot. Imagine a picture consisting of 1000 points. If you wish to
                change the color of all points to green, it would be quite cumbersome to set
                PointColor = RGB::Green in all 1000 points. Instead, you can set
                PointColor = RGB::Green in the PointColor defaults entry at some tree node that
                contains all the points (e.g., the canvas), either directly in the plot call or via the
                object browser/property inspector. Similarly, if there are 1000 points in one scene
                and another 1000 points in a second scene, you can change the color of all points
                in the first scene by an appropriate default entry in the first scene, whilst the
                default entry for the second scene can be set to a different value. See page 11-58
                for an example.
     11-52
                                 Viewer, Browser, and Inspector: Interactive Manipulation
A 3D plot can be rotated and shifted by the mouse. Also zooming in and out is
possible. In fact, these operations are realized by moving the camera around,
closer to, or farther away from the scene, respectively. There is a camera control
that may be switched on and off via the ‘Camera Control’ item of the ‘View’ menu
or the camera icon in the toolbar. It provides the current viewing parameters such
as camera position, focal point and the angle of the camera lens:
                                                                                     11-53
11   Graphics
     Primitives
                  In this section, we give a brief survey of the graphical primitives, grouping
                  constructs, transformations etc. provided by the plot library.
                  The following table lists the ‘low-level’ primitives:
                                                                                                 
                    Arc2d, Arc3d                              circular arc,
                    Arrow2d, Arrow3d                          arrow,
                    Box                                       rectangular box in 3D,
                    Circle2d, Circle3d                        circle,
                    Cone                                      cone/conical frustum in 3D,
                    Cylinder                                  cylinder in 3D,
                    Ellipse2d, Ellipse3d                      ellipse,
                    Ellipsoid                                 ellipsoid in 3D,
                    Line2d, Line3d                            (finite or infinite) line,
                    Parallelogram2d, Parallelogram3d parallelogram,
                    Plane                                     infinte plane in 3D,
                    Point2d, Point3d                          point,
                    PointList2d, PointList3d                  list of points,
                    Polygon2d, Polygon3d                      line segments forming a polygon,
                    Rectangle                                 rectangle in 2D,
                    Sphere                                    sphere in 3D,
                    SurfaceSet                                surface in 3D
                                                              (as a collection of triangles),
                    SurfaceSTL                                import of 3D stl surfaces,
                    Text2d, Text3d                            text object.
                                                                                                 
                  In addition, there are primitives plot::Tetrahedron, plot::Hexahedron,
                  plot::Octahedron, plot::Dodecahedron, and plot::Icosahedron for Plato’s
                  regular polyhedra and plot::Waterman for Waterman polyhedra.
                  The following table lists the ‘high-level’ primitives and ‘special purpose’
                  primitives:
     11-54
                                                                          Primitives
                                                                             
    Bars2d, Bars3d               (statistical) data plot,
    Boxplot                      (statistical) box plot,
    Conformal                    plot of conformal functions in 2D,
    Curve2d, Curve3d             parameterized curve,
    Cylindrical                  surface in cylindrical coordinates in 3D,
    Density                      density plot in 2D,
    Function2d, Function3d       function graph,
    Hatch                        hatched region in 2D,
    Histogram2d                  (statistical) histogram plot in 2D,
    Implicit2d                   implicitly defined curves in 2D,
    Implicit3d                   implicitly defined surfaces in 3D,
    Inequality                   visualization of inequalities in 2D,
    Iteration                    visualization of iterations in 2D,
    Listplot                     finite list of points,
    Lsys                         Lindenmayer system in 2D,
    Matrixplot                   visualization of matrices in 3D,
    Ode2d, Ode3d                 graphical solution of an ODE,
    Piechart2d, Piechart3d       (statistical) pie chart,
    Polar                        curve in polar coordinates in 2D,
    Prism                        prism in 3D,
    Pyramid                      pyramids and their frustrums in 3D,
    QQPlot                       (statistical) quantile-quantile plots,
    Raster                       raster and bitmap plots in 2D,
    Rootlocus                    dependency of rational root on parameter,
    Scatterplot                  (statistical) scatter plot in 2D,
    Sequence                     sequence (given by formula) in 2D,
    SparseMatrixplot             sparsity pattern of a matrix, 2D,
    Spherical                    surface in spherical coordinates in 3D,
    Streamlines2d                vector field visualization in 2D,
    Sum                          visualization of symbolic sums in 2D,
    Sweep                        sweep surface spanned by two curves in 3D,
    Tube                         tube plot in 3D,
    Turtle                       turtle plot in 2D,
    VectorField2d, VectorField3d vector field plot,
    Surface                      parameterized surface in 3D,
    XRotate                      surface of revolution in 3D,
    ZRotate                      surface of revolution in 3D.
                                                                             
                                                                              11-55
11   Graphics
                The following table lists the various light sources available to illuminate 3D plots:
                                                                                                     
                  AmbientLight ambient (undirected) light,
                  DistantLight directed light (sun light),
                  PointLight      (undirected) point light,
                  SpotLight       (directed) spot light.
                                                                                                     
                The following table lists various grouping constructs:
                                                                                                    
                  Canvas                   drawing area,
                  Scene2d                  container for 2D coordinate systems,
                  Scene3d                  container for 3D coordinate systems,
                  CoordinateSystem2d container for 2D primitives,
                  CoordinateSystem3d container for 3D primitives,
                  Group2d                  group of primitives in 2D,
                  Group3d                  group of primitives in 3D.
                                                                                                    
                Primitives or groups of primitives can be transformed by the following objects:
                                                                                                    
                  Scale2d, Scale3d              scaling,
                  Reflect2d, Reflect3d          reflection,
                  Rotate2d, Rotate3d            rotation,
                  Translate2d, Translate3d translation,
                  Transform2d, Transform3d general linear transformation.
                                                                                                    
                Additionally, there are:
                                                                                                    
                  Camera         camera in 3D,
                  ClippingBox clipping box in 3D.
                                                                                                    
     11-56
                                                                                                Attributes
Attributes
             The plot library provides more than 400 attributes for fine-tuning of the
             graphical output. Because of this large number, the attributes are grouped into
             various categories in the object browser (see page 11-50) and the documentation:
                                                                                             
               category       meaning
              Animation       parameters relevant for animations
              Annotation      footer, header, titles, and legends
              Axes            axes style and axes titles
              Calculation     numerical evaluation
              Definition      parameters that change the object itself
              Grid Lines      grid lines in the background (rulings)
              Layout          layout parameters for canvas and scenes
              Style           parameters that do not change the objects but their
                              presentation (visibility, color, line width, point size etc.)
                 Arrows       style parameters for arrows
                 Lines        style parameters for line objects
                 Points       style parameters for point objects
                 Surface      style parameters for surface objects in 3D
                              and filled areas in 2D
              Tick Marks      axes tick marks: style and labels
                                                                                                     
             On the help page for each primitive, there is a complete list of all attributes the
             primitive reacts to. Clicking on an attribute, you are lead to the help page for this
             attribute which provides all the necessary information concerning its semantics
             and admissible values. The examples on the help page demonstrate the typical use
             of the attribute.
Default Values
             Most attributes have a default value that is used if no value is specified explicitly.
             As an example, we consider the attribute LinesVisible that is used by several
             primitives such as plot::Box, plot::Circle2d, plot::Cone, plot::Curve2d,
             plot::Raster etc. Although they all use the same attribute named LinesVisible,
             its default value differs among the different primitive types. The specific defaults
                                                                                                      11-57
11   Graphics
                 plot::getDefault(plot::Box::LinesVisible),
                 plot::getDefault(plot::Circle2d::LinesVisible),
                 plot::getDefault(plot::Cone::LinesVisible),
                 plot::getDefault(plot::Raster::LinesVisible)
                    TRUE, TRUE, TRUE, FALSE
                If any of the default values provided by the MuPAD® system do not seem
                appropriate for your applications, change these defaults via plot::setDefault:
                 plot::setDefault(plot::Box::LinesVisible = FALSE)
                    TRUE
                (The return value is the previously valid default value.) Several defaults can be
                changed simultaneously:
                 plot::setDefault(plot::Box::LinesVisible = FALSE,
                                  plot::Circle2d::LinesVisible = FALSE,
                                  plot::Circle2d::Filled = TRUE)
                    FALSE, TRUE, FALSE
                 plot::getDefault(plot::Box::LinesVisible)
                    FALSE
Inheritance of Attributes
                The setting of default values for attributes is quite sophisticated. Assume that you
                have two scenes that are to be displayed in one single canvas. Both scenes consist
                of 51 graphical points, each:
                 points1 := plot::Point2d(i/50*PI, sin(i/50*PI)) $ i=0..50:
                 points2 := plot::Point2d(i/50*PI, cos(i/50*PI)) $ i=0..50:
                 S1 := plot::Scene2d(points1):
                 S2 := plot::Scene2d(points2):
     11-58
                                                                                     Attributes
plot(S1, S2)
If we wish to color all points in both scenes red, we can set a default for the point
color in the plot command:
 plot(S1, S2, PointColor = RGB::Red)
If we wish to color all points in the first scene red and all points in the second
scene blue, we can give each of the points the desired color in the generating call
to plot::Point2d. Alternatively, we can set separate defaults for the point color
inside the scenes:
 S1 := plot::Scene2d(points1, PointColor = RGB::Red):
 S2 := plot::Scene2d(points2, PointColor = RGB::Blue):
 plot(S1, S2)
Here is the general rule for setting defaults inside a graphical tree (see page 11-46):
                                                                                    
 When an attribute is specified in a node of the graphical tree, the specified value
 serves as the default value for the attribute for all primitives that exist in the
 subtree starting from that node.
                                                                                    
The default value can be overwritten by another value at each node further down
in the subtree (e.g., finally, by a specific value in the primitives). In the following
call, the default color ‘red’ is set in the canvas. This value is accepted and used in
                                                                                          11-59
11   Graphics
                the first scene. The second scene sets the default color ‘blue’ overriding the default
                value ‘red’ set in the canvas. Additionally, there is an extra point with a color
                explicitly set to ‘black’. This point ignores the defaults set further up in the tree
                hierarchy:
                 extrapoint := plot::Point2d(1.4, 0.5,
                                             PointSize = 3*unit::mm,
                                             PointColor = RGB::Black):
                 S1 := plot::Scene2d(points1, extrapoint):
                 S2 := plot::Scene2d(points2, extrapoint,
                                     PointColor = RGB::Blue):
                 plot(plot::Canvas(S1, S2, PointColor = RGB::Red))
                The following call generates the same result. Note that the plot command
                automatically creates a canvas object and passes the attribute
                PointColor =RGB::Red to the canvas:
                 plot(S1, S2, PointColor = RGB::Red)
                We note that there are different primitives that react to the same attribute. We
                used LinesVisible in the previous section to demonstrate this fact. One of the
                rules for inheriting attributes in a graphical tree is:
                                                                                                    
                 If an attribute such as LinesVisible = TRUE is specified in some node of the
                 graphical tree, all primitives below this node that react to this attribute use the
                 specified value as the default value.
                 If a type specific attribute (using the “fully qualified” syntax) such as
                 plot::Circle2d::LinesVisible = TRUE is specified, the new default value is
                 valid only for primitives of that specific type.
                                                                                                    
     11-60
                                                                               Attributes
We wish to turn the circles into filled circles by setting Filled = TRUE and
LinesVisible = FALSE:
 plot(rectangle, circles,
      Filled = TRUE, FillPattern = Solid,
      LinesVisible = FALSE, Axes = Frame)
                                                                                   11-61
11   Graphics
                This is not quite what we wanted: Not only the circles, but also the rectangle
                reacts to the attributes Filled, FillPattern, and LinesVisible. The following
                command restricts these attributes to the circles:
                 plot(rectangle, circles,
                      plot::Circle2d::Filled = TRUE,
                      plot::Circle2d::FillPattern = Solid,
                      plot::Circle2d::LinesVisible = FALSE,
                      Axes = Frame)
                The default values for the attributes are chosen in such a way that they produce
                reasonable pictures in “typical” plot commands. For example, the default axes
                type in 3D scenes is Axes = Boxed, because this is the most appropriate axes type in
                the majority of 3D plots:
                 plot::getDefault(plot::CoordinateSystem3d::Axes)
                    Boxed
                However, there are exceptions. E.g., a plot containing a 3D pie chart should
                probably have no axes at all. Since it is not desirable to use Axes = None as the
                default setting for all plots, exceptional primitives such as plot::Piechart3d are
     11-62
                                                                                     Attributes
given a chance to override the default axes automatically. In a pie chart plot, no
axes are used by default:
 plot(plot::Piechart3d([20,        30, 10, 7, 20, 13],
              Titles = [1 =        "20%", 2 = "30%",
                        3 =        "10%", 4 = "7%",
                        5 =        "20%", 6 = "13%"]))
Note that the attribute Axes that is in charge of switching axes on and off is a
scene attribute and hence cannot be processed by pie chart objects directly.
Hence, a separate mechanism for requesting special scene attributes by primitives
is implemented: so-called “hints.”
A “hint” is an attribute of one of the superordinate nodes in the graphical tree, i.e.,
an attribute of a coordinate system, a scene, or the canvas. The help pages of the
primitives give information on what hints are sent by the primitive. If several
primitives send conflicting hints, the first hint is used.
Hints are implemented internally and cannot be switched off by the user. Note,
however, that the hints concept only concerns default values for attributes. You
can always specify the attribute explicitly if you think that a default value or a hint
is not appropriate.
                                                                                          11-63
11   Graphics
     11-64
                                                                                    Attributes
We have a brief look at a typical help page for a plot attribute to explain the
information provided there:
                                                                                     
    UMesh, VMesh, USubmesh, VSubmesh – number of sample
    points
    The attributes UMesh etc. determine the number of sample points used for the
    numerical approximation of parameterized plot objects such as curves and
    surfaces.
    → Examples
        Attribute                 Type         Value
        USubmesh, VSubmesh        inherited    non-negative integer
        UMesh, VMesh              inherited    positive integer
    See Also
     AdaptiveMesh, Mesh, Submesh, XMesh, YMesh, ZMesh
    Objects reacting to UMesh, VMesh, USubmesh, VSubmesh
        plot::Surface, plot::Cylindrical,               25 (UMesh, VMesh)
        plot::XRotate, plot::Spherical,                 0 (USubmesh,
        plot::ZRotate                                   VSubmesh)
        plot::Tube                                      60 (UMesh)
                                                        11 (VMesh)
                                                        0 (USubmesh)
                                                        1 (VSubmesh)
    …
    Detail
         • Many plot objects have to be evaluated numerically on a discrete mesh.
           …
    Example 1 …
                                                                                     
                                                                                       11-65
11   Graphics
                   • the table entry “Type” (“inherited”) states that these attributes may not only
                     be specified in the generating call of graphical primitives. They can also be
                     specified at higher nodes of a graphical tree to be inherited by the primitives
                     in the corresponding subtree (see page 11-58).
                   • the table entry “Value” states the type of the number n that is admissible
                     when passing the attributes UMesh = n, VMesh = n etc.
     11-66
                                                                                                 Colors
Colors
         The most prominent plot attribute, available for almost all primitives, is Color,
         setting the ‘primary’ color of an object. MuPAD® ’s plot library knows 3 different
         types of primary colors:
            • The attribute PointColor refers to the color of points in 2D and 3D (of type
              plot::Point2d and plot::Point3d, respectively).
            • The attribute LineColor refers to the color of line objects in 2D and 3D. This
              includes the color of function graphs in 2D, curves in 2D and 3D, polygon
              lines in 2D and 3D etc. Also 3D objects such as function graphs in 3D,
              parametrized surfaces etc. react to the attribute LineColor; it defines the
              color of the coordinate mesh lines that are displayed on the surface.
            • The attribute FillColor refers to the color of closed and filled polygons in
              2D and 3D as well as hatched regions in 2D. Further, it sets the surface color
              of function graphs in 3D, parametrized surfaces etc. This includes spheres,
              cones etc.
         The primitives also accept the attribute Color as a shortcut for one of these colors.
         Depending on the primitive, either PointColor, LineColor, or FillColor is set
         with the Color attribute.
RGB Colors
         MuPAD® uses the RGB color model, i.e., colors are specified by lists [r, g, b] of
         red, green, and blue values between 0 and 1, or in HTML syntax as a hash mark
         followed by a six-digit hexadecimal number, as in #cc0099. Black and white
         correspond to [0, 0, 0] (#000000) and [1, 1, 1] (#ffffff), respectively. The
         library RGB contains numerous color names with corresponding RGB values:
          RGB::Black, RGB::White, RGB::Red, RGB::SkyBlue
             [0.0, 0.0, 0.0] , [1.0, 1.0, 1.0] , [1.0, 0.0, 0.0] , [0.0, 0.8, 1.0]
         List all color names available in the RGB library via info(RGB). Alternatively, there
         is the command RGB::ColorNames() returning a complete list of names. With
                                                                                                 11-67
11   Graphics
                 RGB::ColorNames(Red)
                   [CadmiumRedDeep, CadmiumRedLight, CardinalRed,
                one searches for all color names that contain ‘Red.’ To actually see the colors
                found, use RGB::plotColorPalette:
                 RGB::plotColorPalette("red")
                After exporting the color library via use(RGB), you can use the color names in the
                short form Black, White, IndianRed etc. Note, however, that this command will
                assign values to a little over 350 identifiers, precluding their use in other meanings.
                RGBa color values consist of lists [r, g, b, a] containing a fourth entry: the
                “opacity” value a between 0 and 1. (In HTML-like notation, the hexadecimal
                specification has eight characters.) For a = 0, a surface patch painted with this
                RGBa color is fully transparent (i.e., invisible). For a = 1, the surface patch is
                opaque, i.e., it hides plot objects that are behind it. For 0 < a < 1, the surface
                patch is semi-transparent, i.e., plot objects behind it shine through.
                RGBa color values can be constructed easily via the RGB library. One only has to
                append a fourth entry to the [r, g, b] lists provided by the color names. The easiest
     11-68
                                                                                 Colors
way to do this is to append the list [a] to the RGB list via the concatenation
operator ‘.’. We create a semi-transparent gray:
 RGB::Gray.[0.5]
     [0.752907, 0.752907, 0.752907, 0.5]
HSV Colors
Besides the RGB model, there are various other popular color formats used in
computer graphics. One is the HSV model (Hue, Saturation, Value). The RGB
library provides the routines RGB::fromHSV and RGB::toHSV to convert HSV
                                                                                 11-69
11   Graphics
                 RGB::fromHSV(hsv) = RGB::Orange
                    [1.0, 0.4, 0.0] = [1.0, 0.4, 0.0]
                With the RGB::fromHSV utility, all colors in a MuPAD plot can be specified easily
                as HSV colors. For example, the color ‘violet’ is given by the HSV values
                [290, 0.4, 0.6], whereas ‘dark green’ is given by the HSV specification
                [120, 1, 0.4] (120 for ‘green,’ 0.4 for ‘dark’). Hence, a semi-transparent violet
                sphere intersected by an opaque dark green plane may be specified as follows:
                 plot(plot::Sphere(1, [0, 0, 0],
                         Color = RGB::fromHSV([290, 0.4, 0.6, 0.5])),
                      plot::Surface([x, y, 0.5], x = -1..1, y = -1..1,
                         Mesh = [2, 2],
                         Color = RGB::fromHSV([120, 1, 0.4])))
     11-70
                                                                                             Animations
Animations
             Each primitive of the plot library knows how many specifications of type “range”
             it has to expect.
                                                                                           
              Whenever a graphical primitive receives a “surplus” range specification by
              an equation such as a = amin..amax, the parameter a is interpreted as an “an-
              imation parameter” assuming values from amin to amax.
                                                                                           
             expects one plot range for the x coordinate, whereas a static bi-variate function
             graph in 3D expects two plot ranges for the x and y coordinate:
              plot::Function3d(sin(x^2 + y^2), x = 0..2, y = 0..2):
             Thus, it is very easy indeed to create animated objects: just pass a “surplus” range
             equation a = amin..amax to the generating call of the primitive. The name a of the
             animation parameter is irrelevant; any symbolic name may be used. All other
                                                                                                    11-71
11   Graphics
                entries and attributes of the primitive that are symbolic expressions of the
                animation parameter will be animated. In the following call, both the function
                expression as well as the x range of the function graph depend on the animation
                parameter. Also, the ranges defining the width and the height of the rectangle as
                well as the end point of the line depend on it:
                 plot(plot::Function2d(a*sin(x), x = 0..a*PI, a = 0.5..1),
                      plot::Rectangle(0..a*PI, 0..a, a = 0.5..1,
                                      LineColor = RGB::Black),
                      plot::Line2d([0, 0], [PI*a, a], a = 0.5 ..1,
                                   LineColor = RGB::Black))
     11-72
                                                                                   Animations
Here is an animated arc whose radius and “angle range” depend on the animation
parameter:
 plot(plot::Arc2d(1 + a, [0, 0], AngleRange = 0..a*PI,
                  a = 0..1))
                                                                                       11-73
11   Graphics
                In the following example, different names a and b are used for the animation
                parameters of the two functions:
                 plot(plot::Function2d(4*a*x, x = 0..1, a = 0..1),
                      plot::Function2d(b*x^2, x = 0..1, b = 1..4))
     11-74
                                                                                 Animations
receives the animation parameter. One finds that for Function3d, the fill color
function is called with the coordinates x, y , z of the points on the graph. The next
input parameter (the 4th argument of mycolor) is the animation parameter:
 f := (x, y) -> 4 - (x - a)^2 - (y - a)^2:
 mycolor := proc(x, y, z, a)
   local t;
 begin
   t := sqrt((x - a)^2 + (y - a)^2):
   if t < 0.1 then return(RGB::Red)
   elif t < 0.4 then return(RGB::Orange)
   elif t < 0.7 then return(RGB::Green)
   else return(RGB::Blue)
   end_if;
 end:
 plot(plot::Function3d(f, x = -1..1, y = -1..1, a = -1..1,
                       FillColorFunction = mycolor))
Playing Animations
When an animated plot is created in a MuPAD® notebook, the first frame of the
animation appears as a static picture below the input region. To start the
                                                                                        11-75
11   Graphics
                animation, click on the plot. An icon for stopping and re-starting the animation
                will appear (make sure the item ‘Animation Bar’ of the ‘View’ menu is enabled):
One can also use the slider to animate the picture “by hand.”
                Increasing the number of frames does not mean that the animation runs longer;
                the renderer does not work with a fixed number of frames per second but
                processes all frames within a fixed time interval.
     11-76
                                                                                Animations
In the background, there is a “real time clock” used to synchronize the animation
of different animated objects. An animation has a time range measured by this
clock. The time range is set by the attributes TimeBegin = t0, TimeEnd = t1 or,
equivalently, TimeRange = t0..t1, where t0, t1 are real numerical values
representing physical times in seconds. These attribute can be set in the
generating call of the animated primitives, or at some higher node of the graphical
tree. In the latter case, these attributes are inherited by all primitives that exist
below the node.
The absolute value of t0 is irrelevant if all animated objects share the same time
range. Only the time difference t1 - t0 matters. It is (an approximation of) the
physical time in seconds that the animation will last.
                                                                                   
 The parameter range amin..amax in the specification of the animation param-
 eter a = amin..amax together with Frames = n defines an equidistant time mesh
 in the time interval set by TimeBegin = t0 and TimeEnd = t1. The frame with
 a = amin is visible at the time t0, the frame with a = amax is visible at the time
 t1.
                                                                                   
                                                                              
 With the default TimeBegin = 0, the value of the attribute TimeEnd gives the
 physical time of the animation in seconds. The default value is TimeEnd = 10,
 i.e., an animation using the default values will last about 10 seconds. The
 number of frames set by Frames = n does not influence the time interval, but
 changes the number of frames displayed in this time interval.
                                                                              
The point will be animated for about 5 physical seconds in which it moves along
one period of the sine graph. Each frame is displayed for about 0.1 seconds. After
increasing the number of frames by a factor of 2, each frame is displayed for about
0.05 seconds, making the animation somewhat smoother:
 plot(plot::Point2d([a, sin(a)], a = 0..2*PI,
                    Frames = 100, TimeRange = 0..5))
                                                                                        11-77
11   Graphics
                Note that the human eye cannot distinguish between different frames if they
                change with a rate of more than 25 frames per second. Thus, the number of
                frames n set for the animation should satisfy
n < 25 · (t1 − t0 ).
                Hence, with the default time range TimeBegin = 0, TimeEnd = 10 (seconds), it does
                not make sense to specify Frames = n with n > 250. If a higher frame number is
                required to obtain a sufficient resolution of the animated object, one should also
                increase the time for the animation by a sufficiently high value of TimeEnd.
                The answer is: “Almost any attribute can be animated!” Instead of listing the
                attributes that allow animation, it is much easier to characterize the attributes
                that cannot be animated:
     11-78
                                                                                  Animations
   • The texts of annotations such as Footer, Header, Title, legend entries etc.
     cannot be animated. The position of titles, however, can be animated.
     There are special text objects plot::Text2d and plot::Text3d that allow to
     animate the text as well as their position.
Nearly all attributes not falling into one of these categories can be animated. You
will find detailed information on this issue on the corresponding help pages of
primitives and attributes.
As already explained on page 11-76, there is a “real time clock” running in the
background that synchronizes the animation of different animated objects.
Each animated object has its own separate “real time life span” set by the
attributes TimeBegin = t0, TimeEnd = t1 or, equivalently, TimeRange = t0..t1. The
values t0, t1 represent seconds measured by the “real time clock.”
                                                                                      11-79
11   Graphics
                In most cases, there is no need to bother about specifying the life span. If
                TimeBegin and TimeEnd are not specified, the default values TimeBegin = 0 and
                TimeEnd = 10 are used, i.e., the animation will last about 10 seconds. These values
                only need to be modified
                Here is an example for the second situation. The plot consists of 3 jumping points.
                For the first 5 seconds, the left point jumps up and down, while the other points
                remain at their initial position. Then, all points stay static for 1 second. After a
                total of 6 seconds, the middle point starts its animation by jumping up and down,
                while the left point remains static in its final position and the right points stays
                static in its initial position. After 9 seconds, the right point begins to move as well.
                The overall time span for the animation is the hull of the time ranges of all
                animated objects, i.e., 15 seconds in this example:
                 p1 := plot::Point2d(-1, sin(a), a = 0..PI,
                                     Color = RGB::Red,
                                     TimeBegin = 0, TimeEnd = 5):
                 p2 := plot::Point2d(0, sin(a), a = 0..PI,
                                     Color = RGB::Black,
                                     TimeBegin = 6, TimeEnd = 12):
                 p3 := plot::Point2d(1, sin(a), a = 0..PI,
                                     Color = RGB::Blue,
                                     TimeBegin = 9, TimeEnd = 15):
     11-80
                                                                             Animations
Here, all points use the default settings VisibleBeforeBegin = TRUE and
VisibleAfterEnd = TRUE which make them visible as static objects outside the
time range of their animation. We set VisibleAfterEnd = FALSE for the middle
point, so that it disappears after the end of its animation. With
VisibleBeforeBegin = FALSE, the right point is not visible until its animation
starts:
 p2::VisibleAfterEnd := FALSE:
 p3::VisibleBeforeBegin := FALSE:
                                                                                 11-81
11   Graphics
                   • When a plot containing animated objects is created, the real time clock is set
                     to the minimum of the TimeBegin values of all animated objects in the plot.
                     The real time clock is started when pushing the ‘play’ button for animations
                     in the graphical user interface.
                   • Before the real time reaches the TimeBegin value t0 of an animated object,
                     this object is static in the state corresponding to the begin of its animation.
                     Depending on the attribute VisibleBeforeBegin, it may be visible or
                     invisible before t0.
                   • During the time from t0 to t1, the object changes from its original to its final
                     state.
     11-82
                                                                                Animations
   • After the real time reaches the TimeEnd value t1, the object stays static in the
     state corresponding to the end of its animation. Depending on the value of
     the attribute VisibleAfterEnd, it may stay visible or become invisible after
     t1.
   • The animation of the entire plot ends with the physical time given by the
     maximum of the TimeEnd values of all animated objects in the plot.
There are some special attributes such as VisibleAfter that are very useful to
build animations from purely static objects:
                                                                                 
 With VisibleAfter = t0, an object is invisible from the start of the animation
 until time t0. Then it will appear and remain visible for the rest of the anima-
 tion.
                                                                                 
                                                                               
 With VisibleBefore = t1, an object is visible from the start of the animation
 until time t1. Then it will disappear and remain invisible for the rest of the
 animation.
                                                                               
                                                                                        11-83
11   Graphics
                We add a further point p4 that is not animated. We make it invisible at the start of
                the animation via the attribute VisibleFromTo. It is made visible after 7 seconds
                to disappear again after 13 seconds:
                 p4 := plot::Point2d(0.5, 0.5, Color = RGB::Black,
                                     VisibleFromTo = 7..13):
     11-84
                                                                                Animations
Here is an example. We let two points wander along the graphs of the sine and the
cosine function, respectively. Each frame is to consist of a picture of two points.
We use plot::Group2d to define the frame; the group forwards the attribute
VisibleFromTo to all its elements:
 for i from 0 to 101 do
     t[i] := i/10;
 end_for:
 for i from 0 to 100 do
   x := i/100*PI;
   myframe[i] := plot::Group2d(
          plot::Point2d([x, sin(x)], Color = RGB::Red),
          plot::Point2d([x, cos(x)], Color = RGB::Blue),
          VisibleFromTo = t[i]..t[i + 1]);
 end_for:
                                                                                      11-85
11   Graphics
                This “frame by frame” animation certainly needs a little bit more coding effort
                than the equivalent object-wise animation, where each of the points is animated.
     11-86
                                                                                  Animations
Compare:
 delete i:
 plot(plot::Point2d([i/100*PI, sin(i/100*PI)],
                     i = 0..100, Color = RGB::Red),
      plot::Point2d([i/100*PI, cos(i/100*PI)],
                     i = 0..100, Color = RGB::Blue),
      Frames = 101, PointSize = 7.0*unit::mm)
There is a special kind of plot where “frame by frame” animations are very useful.
Note that in the present version of the graphics, new plot objects cannot be added
to a scene that is already rendered. With the special “visibility” animations for
static objects, however, one can easily simulate a plot that gradually builds up: fill
the frames of the animation with static objects that are visible for a limited time
only. The visibility can be chosen very flexibly by the user. For example, the static
objects can be made visible only for one frame (VisibleFromTo) which allows to
simulate moving objects.
                                                                                         11-87
11   Graphics
     11-88
                                                            Animations
                                                                11-89
11   Graphics
Examples
     11-90
                                                                          Animations
Example 2: We build two 3D animations. The first one starts with a rectangular
strip that is deformed to an annulus in the x, y plane:
 c := a -> 1/2 *(1 - 1/sin(PI/2*a)):
 mycolor := (u, v, x, y, z) ->
                [(u - 0.8)/0.4, 0, (1.2 - u)/0.4]:
 rectangle2annulus := plot::Surface(
    [c(a) + (u-c(a))*cos(PI*v), (u-c(a))*sin(PI*v), 0],
    u = 0.8..1.2, v = -a..a, a = 1/10^10..1,
    FillColorFunction = mycolor, Mesh = [3, 40],
    Frames = 40):
                                                                                 11-91
11   Graphics
     11-92
                                                                                 Animations
Note that the final frame of the first animation coincides with the first frame of the
second animation. To join the two separate animations, we can set appropriate
visibility ranges and plot them together. After 5 seconds, the first animation
object vanishes and the second takes over:
 rectangle2annulus::VisibleFromTo := 0..5:
 annulus2moebius::VisibleFromTo := 5..7:
                                                                                         11-93
11   Graphics
                plot(rectangle2annulus, annulus2moebius,
                     Axes = None, CameraDirection = [-11, -3, 3])
     11-94
                                                                                      Groups of Primitives
Groups of Primitives
              An arbitrary number of graphical primitives in 2D or 3D can be collected in
              groups of type plot::Group2d or plot::Group3d, respectively. This is useful for
              handing down attribute values to all elements in a group.
              In the following example, we visualize random generators with different
              distributions by using them to position random points:
               r1 := stats::normalRandom(0, 1):
               group1 := plot::Group2d(plot::Point2d(r1(),            r1())
                                                     $ i =            1..200):
               r2 := stats::uniformRandom(-3, 3):
               group2 := plot::Group2d(plot::Point2d(r2(),            r2())
                                                     $ i =            1..500):
               plot(group1, group2, Axes = Frame)
              We cannot distinguish between the two kinds of points. Due to the grouping, it is
              very easy to change their color, size, and style by setting the appropriate attributes
              in the groups. Now, the two kinds of points can be distinguished easily:
                                                                                                       11-95
11   Graphics
                group1::PointColor := RGB::Red:
                group1::PointStyle := XCrosses:
                group2::PointColor := RGB::Blue:
                group2::PointSize := 0.7*unit::mm:
                plot(group1, group2, Axes = Frame)
     11-96
                                                                                                   Transformations
Transformations
             Affine linear transformations ⃗x → A · ⃗x + ⃗b with a vector ⃗b and a matrix A can be
             applied to graphical objects via transformation objects. There are special
             transformations such as translations, scaling, and rotations as well as general
             affine linear transformations:
                                                                                                              11-97
11   Graphics
                The ellipses plot::Ellipse2d provided by the plot library have axes parallel to
                the coordinate axes. We use a rotation to create an ellipse with a different
                orientation:
                 center := [1, 2]:
                 ellipse := plot::Ellipse2d(2, 1, center):
                 plot(plot::Rotate2d(PI/4, center, ellipse))
                Transform objects can be animated. We build a group consisting of the ellipse and
                its symmetry axes. An animated rotation is applied to the group:
                 g := plot::Group2d(ellipse,
                           plot::Line2d([center[1] + 2, center[2]],
                                        [center[1] - 2, center[2]]),
                           plot::Line2d([center[1], center[2] + 1],
                                        [center[1], center[2] - 1])):
     11-98
                                                  Transformations
                                                           11-99
11   Graphics
     Legends
                The annotations of a MuPAD® plot may include a legend. A legend is a small table
                that relates the color of an object with some text explaining the object:
                 f := 3*x*sin(2*x):
                 g := 4*x^2*cos(x):
                 h := sin(4*x)/x:
                 plotfunc2d(f, g, h, x = 0..PI/2):
     11-100
                                                                             Legends
A corresponding plot command using primitives of the plot library does not
generate the legend automatically:
 plot(plot::Function2d(f, x = 0..PI/2, Color = RGB::Red),
      plot::Function2d(g, x = 0..PI/2, Color = RGB::Green),
      plot::Function2d(h, x = 0..PI/2, Color = RGB::Blue))
                                                                              11-101
11   Graphics
                Each graphical primitive accepts the attribute Legend. Passing this attribute to an
                object triggers several actions:
                   • A hint is sent to the scene containing the object advising it to use the scene
                     attribute LegendVisible = TRUE.
                The attributes LegendText and LegendEntry are visible in the “object inspector” of
                the interactive viewer (page 11-50) and can be manipulated interactively for each
                single primitive after selection in the “object browser.” The attribute
                LegendVisible is associated with the scene object accessible via the “object
                browser.”
     11-102
                                                                                                Legends
• If the attribute LegendText is specified, its value is used for the legend text.
    • If no LegendText is specified, but the Name attribute is set, the name is used
      for the legend text.
                                                                                                11-103
11   Graphics
     Fonts
                The plot attributes for specifying fonts are AxesTitleFont, FooterFont,
                HeaderFont, LegendFont, TextFont, TicksLabelFont, and TitleFont. Each such
                font is specified by a MuPAD® list containing any of the following:
                   • A string denoting the font family: the available font families depend on the
                     fonts that are installed on your machine. Typical font families available on
                     Windows systems are "Times New Roman" (of type "serif"), "Arial" (of
                     type "sans-serif"), or "Courier New" (of type "monospace").
                     To find out which fonts are available on your machine, open the menu
                     ‘Format,’ submenu ‘Font’ in your MuPAD notebook. The first column in the
                     font dialog provides the names of the font families that you may specify.
                     The most portable way of defining fonts is to use one the three generic
                     family names "serif", "sans-serif", or "monospace". The system will
                     automatically choose one of the available font families of the specified type
                     for you.
• A color specification.
     11-104
                                                                                   Fonts
In the following example, we specify the font for the canvas header and footer:
 plot(plot::Function2d(sin(x), x = 0..2*PI),
      Header = "The sine function",
      HeaderFont = ["monospace", 12, Bold],
      Footer = "The sine function",
      FooterFont = ["Times New Roman", 14, Italic])
                                                                                  11-105
11   Graphics
                All font parameters are optional; some default values are chosen for entries that
                are not specified. For example, if you do not care about the footer font family for
                your plot, but you insist on a specific font size, you may specify a 14 pt font as
                follows:
                 plot(plot::Function2d(sin(x), x = 0..2*PI),
                      Footer = "The sine function", FooterFont = [14])
     11-106
                                                                          Saving and Exporting Pictures
              The MuPAD® kernel uses an xml format to communicate with the renderer.
              Usually, a plot command sends a stream of xml data directly to the viewer which
              renders the picture.
              After clicking on the picture, the notebook provides a menu item ‘File/Export
              Graphics…’ that opens a dialog allowing to save the picture in a variety of
              graphical formats:
                 • The image may also be stored in various standard bitmap formats such as
                   png, jpg etc.
                 • MuPAD’s native format is indicated by the file extension ‘xvz’ for the
                   compressed and ‘xvc’ for the uncompressed version.
                   One can use MuPAD to open such files and display and manipulate the plots
                   contained therein.
                                                                                                 11-107
11   Graphics
Batch Mode
                MuPAD plots can also be saved in “batch mode” by specifying the attribute
                OutputFile = filename in a plot call:
                Here, the extension xvz of the file name indicates that MuPAD’s xml data are to be
                written in compressed format. Alternatively, the extension xvc may be used to
                write the xml data without compression of the file (the resulting ascii file can be
                read with any text editor). Files in both formats can be opened by MuPAD to
                generate the plot encoded by the xml data.
                If the MuPAD environment variable WRITEPATH does not have a value, the
                previous call creates the file in the directory where MuPAD is installed. An
                absolute pathname can be specified to place the file anywhere else:
                 plot(Primitive1, Primitive2, ...,
                      OutputFile = "C:\\Documents\\mypicture.xvz")
     11-108
                                                                 Saving and Exporting Pictures
If no file extension is specified by the file name, the default extension xvc is used,
i.e., uncompressed xml data are written.
If a notebook is saved to a file, its location in the file system is available inside the
notebook as the value of the environment variable NOTEBOOKPATH. If you wish to
save your plot in the same folder as the notebook, you may call
 plot(Primitive1, Primitive2, ...,
      OutputFile = NOTEBOOKPATH."mypicture.xvz")
                                                                                            11-109
11   Graphics
     Importing Pictures
                   MuPAD® does not provide for many tools to import standard graphical vector
                   formats, yet. Presently, the only supported vector type is the stl format, popular in
                   stereo lithography, which encodes 3D surfaces. It can be imported via the routine
                   plot::SurfaceSTL.
                   In contrast to graphical vector formats, there are many standard bitmap formats
                   such as bmp, gif, jpg, ppm etc. that can be imported. One can read such a file via
                   import::readbitmap, thus creating a MuPAD array of RGB color values or an
                   equivalent three-dimensional hardware float array that can be manipulated at
                   will. In particular, it can be fed into the routine plot::Raster which creates an
                   object that can be used in any 2D MuPAD plot. Note, however, that the import of
                   bitmap data consumes a lot of memory, i.e., only reasonably small bitmaps (up to
                   a few hundred pixels in each direction) should be processed. Memory
                   consumption is much smaller with hardware floating point arrays, which is why
                   import::reasonably uses them by default.
                   In the following example, we plot the probability density function and the
                   cumulative density function of the standard normal (“Gaussian”) distribution.
                   Paying tribute to Carl Friedrich Gauss, we wish to display «««< .mine his picture
                   in this plot. Assume that we have his picture as a png bitmap file “Gauss.png.” We
                   import the file via import::readbitmap that provides us with the width and
                   height in pixels and the color data: ======= his picture in this plot. Assume that
                   we have his picture as a png bitmap file “Gauss.png.” We import the file via
                   import::readbitmap that provides us with the width and height in pixels and the
                   color data: »»»> .r52548
                    [width, height, gauss] := import::readbitmap("Gauss.png"):
                   Note the colon at the end of the above command! Without it, MuPAD will print
                   the color information on the screen, and formatting such a huge output takes time.
                   We have to use Scaling = Constrained to preserve the aspect ratio of the image.
                   Unfortunately, this setting is not appropriate for the function plots. So we use two
                   different scenes that are positioned via Layout = Relative. See Section ‘Layout of
                   Canvas and Scenes’ of the online plot documentation for details on how the
                   layout of a canvas containing several scenes is set.
     11-110
                                                          Importing Pictures
                                                                     11-111
11   Graphics
     Cameras in 3D
                     The MuPAD® 3D graphics model includes an observer at a specific position,
                     pointing a camera with a lens of a specific opening angle to some specific focal
                     point. The specific parameters “position,” “angle,” and “focal point” determine the
                     picture that the camera will take.
                     When a 3D picture is created,a camera with an appropriate default lens is
                     positioned automatically. Its focal point is chosen as the center of the graphical
                     scene. The interactive viewer allows to rotate the scene which, in fact, is
                     implemented internally as a change of the camera position. Also interactive
                     zooming in and zooming out is realized by moving the camera closer to or farther
                     away from the scene.
                     Apart from interactive camera motions, the perspective of a 3D picture can also be
                     set in the calls generating the plot. One way is to specify the direction from which
                     the camera is pointing towards the scene. This is done via the attribute
                     CameraDirection:
                      plot(plot::Function3d(sin(x + y^3), x = -1..1, y = -1..1),
                           CameraDirection = [-25, 20, 30])
     11-112
                                                                            Cameras in 3D
In these calls, CameraDirection does not fully specify the position of the camera.
This attribute just requests the camera to be placed at some large distance from
the scene along the ray in the direction given by the attribute. The actual distance
from the scene is determined automatically to let the graphical scene fill the
picture optimally.
For a full specification of the perspective, there are camera objects of type
plot::Camera that allow to specify the position of the camera, its focal point and
the opening angle of its lens:
 position := [-5, -10, 5]:
 focalpoint := [0, 0, 0]:
 angle := PI/12:
 camera := plot::Camera(position, focalpoint, angle):
This camera can be passed like any graphical object to the plot command
generating the scene.
                                                                                       11-113
11   Graphics
     11-114
                                                                          Cameras in 3D
                                                                                    11-115
11   Graphics
                Consider the following parameters and the following initial condition Y0:
                 p := 10: r := 28: b := 1: Y0 := [1, 1, 1]:
                With these generators, we create a 3D plot object consisting of the phase curve
                and its projections:
                 object := plot::Ode3d(f, [$ 1..50 step 1/10], Y0,
                     [Gxyz, Style = Splines, Color = RGB::Red],
                     [Gyz, Style = Splines, Color = RGB::LightGray],
                     [Gxz, Style = Splines, Color = RGB::LightGray],
                     [Gxy, Style = Splines, Color = RGB::LightGray]):
     11-116
                                                                         Cameras in 3D
The following plot call takes about half a minute on a 3 GHz computer:
 plot(object, camera, Axes = Boxed, TicksNumber = Low)
Next, we wish to fly along the Lorenz attractor. We cannot use plot::Ode3d,
because we need access to the numerical data of the attractor to build a suitable
animated camera object. We use the numerical ODE solver numeric::odesolve2
and compute a list of numerical sample points on the Lorenz attractor. This takes
about twenty seconds on a 3 GHz computer:
 Y := numeric::odesolve2(f, 0, Y0, RememberLast):
 timemesh := [$ 0..500 step 1/50]:
 Y := [Y(t) $ t in timemesh]:
                                                                                    11-117
11   Graphics
                Similar to the picture above, we define a box around the attractor with the
                projections of the solution curve:
                 box   :=   [-15, 20,   -20, 26, 1, 50]:
                 Yyz   :=   map(Y, pt   -> [box[1], pt[2], pt[3]]):
                 Yxy   :=   map(Y, pt   -> [pt[1], pt[2], box[5]]):
                 Yxz   :=   map(Y, pt   -> [pt[1], box[3], pt[3]]):
                In the a-th frame of the animation, the camera is positioned at the a-th sample
                point of the Lorenz attractor, pointing toward the next sample point. Setting
                TimeRange = 0..n/10, the camera visits about 10 points per second:
     11-118
                                                         Cameras in 3D
n := nops(timemesh) - 1:
plot(plot::Scene3d(
       plot::Camera([Point(a, i) $ i = 1..3],
                    [Point(a + 1, i) $ i = 1..3],
                     PI/4, a = 1..n, Frames = n,
                     TimeRange = 0..n/10),
       plot::Polygon3d(Y, LineColor = RGB::Red,
                       PointsVisible = TRUE),
       plot::Polygon3d(Yxy, LineColor = RGB::DimGray),
       plot::Polygon3d(Yxz, LineColor = RGB::DimGray),
       plot::Polygon3d(Yyz, LineColor = RGB::DimGray),
       plot::Box(box[1]..box[2], box[3]..box[4],
                 box[5]..box[6], Filled = TRUE,
                 LineColor = RGB::Black,
                 FillColor = RGB::Gray.[0.1]),
       BackgroundStyle = Flat))
                                                                11-119
11   Graphics
                   Exercise 11.1: Find alternative display styles for the plots in this chapter.
                   Especially, modify the example from page 11-43 to use plot::Ode2d and/or
                   plot::Streamlines2d.
     11-120
                                                                              12
Output of Expressions
              MuPAD® does not display all computed results on the screen. Typical examples
              are the commands within for loops (Chapter 15) or procedures (Chapter 17): only
              the final result (i.e., the result of the last command) is printed and the output of
              intermediate results is suppressed. Nevertheless, you can let MuPAD print
              intermediate results or change the output format.
              We recall that ithprime(i) computes the i-th prime. MuPAD encloses the text in
              double quotes. Use the option Unquoted to suppress this:
12   Input and Output
                         for i from 4 to 5 do
                           print(Unquoted,
                                 "The ", i, "th prime is ", ithprime(i))
                         end_for
                                The , 4, th prime is , 7
The , 5, th prime is , 11
                                2
                            x
                        Furthermore, you can eliminate the commas from the output by means of the
                        tools for manipulating strings that are presented in Section 4.11:
                         for i from 4 to 5 do
                           print(Unquoted,
                                 "The " . expr2text(i) . "th prime is " .
                                 expr2text(ithprime(i)) . ".")
                         end_for
                                The 4th prime is 7.
                        Here, the function expr2text is used to convert the value of i and the prime
                        returned by ithprime(i) to strings. Then, the concatenation operator . combines
                        them with the other strings to a single string. Note that converting an expression
                        to a string breaks typesetting as well as the “pretty print” format explained below:
                         print(Unquoted, expr2text(x^2))
                                x^2
                        Alternatively you can use the function fprint, which writes data to a file or on the
                        screen. In contrast to print, it does not output its arguments as individual
                        expressions. Instead, fprint combines them to a single string (if you use the
                        option Unquoted):
                         a := one: b := string:
     12-2
                                                                        Output of Expressions
The second argument 0 tells fprint to direct its output to the screen.
                                                                                          12-3
12   Input and Output
                        If an output would exceed the line width, the system automatically breaks the
                        lines:
                         PRETTYPRINT := TRUE: taylor(sin(x), x = 0, 16)
                                 3     5     7       9         11
                               x     x     x       x         x
                           x - -- + --- - ---- + ------ - -------- +
                                 6  120   5040   362880   39916800
                                     13            15
                                   x             x             17
                               ---------- - ------------- + O(x )
                               6227020800   1307674368000
                        You can set the environment variable TEXTWIDTH to the desired line width. Its
                        default value is 75 (characters), and you can assign any integer between 10 and
                        231 − 1 to it. For example, if you compute (ln ln x)′′ , then you obtain the following
                        output:
                         diff(ln(ln(x)), x, x)
                                    1          1
                              - -------- - ---------
                                 2          2      2
                                x ln(x)    x ln(x)
                        If you reduce the value of TEXTWIDTH, the system breaks the output across two
                        lines:
                         TEXTWIDTH := 20: diff(ln(ln(x)),x,x)
                                 1
                           - -------- -
                              2
                             x ln(x)
                                   1
                               ---------
                                2      2
                               x ln(x)
                        You can also control the output by user-defined preferences. This is discussed in
                        the section starting on page 13-2.
     12-4
                                                                                           Reading and Writing Files
              The function write stores the values of identifiers in a file, so that you can reuse
              the computed results in another MuPAD session. In the following example, we
              save the values of the identifiers a and b to the file ab.mb:
               a := 2/3: b := diff(sin(cos(x)), x):
               write("ab.mb", a, b)
              You pass the file name as a string (Section 4.11) enclosed in double quotes ". The
              system then creates a file with this name (without "). If you read this file into
              another MuPAD session via the function read, you can access the values of the
              identifiers a and b without recomputing them:
               reset():
               read("ab.mb"): a, b
                    2
                      , − cos(cos(x)) sin(x)
                    3
              If you use the function write as in the above example, it creates a file in the
              MuPAD binary format. By convention, a file in this format should have the file
              name extension “.mb”. You can call the function write with the option Text. This
              generates a file in a readable text format:1
               a := 2/3: b := exp(x+1):
               write(Text, "ab.mu", a, b)
1 Usually the file name extension for MuPAD text files should be “.mu”. The MuPAD editor allows
                                                                                                                     12-5
12   Input and Output
                        The file ab.mu now contains the following two syntactically correct MuPAD
                        commands:
                        a := 2/3:
                        b := hold(exp)(hold(_plus)(hold(x), 1)):
                        The text format files generated by write contain valid MuPAD commands. Of
                        course, you can use any editor to generate such a text file “by hand” and read it
                        into a MuPAD session, using the command read or the entry ‘Read Commands …’
                        from the ‘Notebook’ menu. In fact this is a natural way to proceed when you
                        develop more complex MuPAD procedures.
                        If you call the function write without supplying any identifiers as arguments, the
                        system writes the values of all identifiers having a value to a file, except for those
                        defined by the MuPADsystem itself. Thus, it is possible to restore the state of the
                        current session via read at a later time:
                         result1 := ...; result2 := ...; ...
                         write("results.mb")
                        Often you want to use data in MuPAD that are generated by other software (for
                        example, you might want to read in statistical values for further processing), or
                        access all files in some directory automatically. This is possible with the help of
                        the function import::readdata from the library import. This function converts
                        the contents of a file to a nested MuPAD list. You may regard the file as a “matrix”
                        with line breaks indicating the beginning of a new row. Note that the rows may
     12-6
                                                              Reading and Writing Files
   1   1.2  12
   2.34 234
     34 345.6
   4    44     444
By default, blank characters are assumed as column separators. So you can read
this file into a MuPAD session as follows:
 data := import::readdata("numericalData"):
 data[1]; data[2]; data[3]; data[4]
    [1, 1.2, 12]
[2.34, 234]
[34, 345.6]
The help page for import::readdata provides further information. Also see
import::csv for another important data exchange format.
                                                                                  12-7
                                                                      13
Utilities
     User-Defined Preferences
                  You can customize MuPAD® ’s behavior by using preferences. The following
                  command lists all preferences:
                   Pref()
                     Pref::abbreviateOutput :       TRUE
                     Pref::alias             :      TRUE
                     Pref::autoExpansionLimit:      1000
                     Pref::autoPlot          :      FALSE
                     Pref::callBack          :      NIL
                     Pref::callOnExit        :      NIL
                     Pref::dbgAutoDisplay    :      TRUE
                     Pref::dbgAutoList       :      TRUE
                     Pref::floatFormat       :      "g"
                     Pref::ignoreNoDebug     :      FALSE
                     Pref::keepOrder         :      DomainsOnly
                     Pref::kernel            :      [5, 6, 0]
                     Pref::maxMem            :      0
                     Pref::maxTime           :      0
                     Pref::output            :      NIL
                     Pref::outputDigits      :      UseDigits
                     Pref::postInput         :      NIL
                     Pref::postOutput        :      NIL
                     Pref::report            :      0
                     Pref::trailingZeroes    :      FALSE
                     Pref::typeCheck         :      Interactive
                     Pref::unloadableModules :      FALSE
                     Pref::userOptions       :      ""
                     Pref::verboseRead       :      0
                     Pref::warnDeadProcEnv   :      FALSE
                  We refer to the help page ?Pref for a complete description of all preferences. Only
                  a few options are discussed below.
                  You can use the report preference to request regular information on MuPAD’s
                  allocated memory, the memory really used, and the elapsed computing time.
                  Valid arguments for report are integers between 0 and 9. The default value 0
                  means that no information is displayed. If you choose the value 9, you
                  permanently obtain information about MuPAD’s current state. You also get this
                  information in the status bar of the notebook, but the output of Pref::report will
     13-2
                                                                 User-Defined Preferences
stay in the output, allowing you to review the development over time.
 Pref::report(9): int(sin(x)^2/x, x = 0..1)
  [used=2880k, reserved=3412k, seconds=1]
  [used=3955k, reserved=4461k, seconds=1]
  [used=7580k, reserved=8203k, seconds=2]
     γ   Ci (2) ln (2)
       −       +
     2     2      2
 Pref::floatFormat("e"): float(exp(-50))
    1.928749848 · 10−22
 Pref::floatFormat("f"): float(exp(-50))
    0.0000000000000000000001928749848
You can use preferences to control the screen output in other ways as well. For
example, after calling Pref::output(F), MuPAD passes every result computed by
the kernel to the function F before printing it on the screen. The screen output is
then the result of the function F instead of the result originally computed by the
kernel. In the following example, we use this to compute and output the
normalization of every requested expression. We define a procedure F
(Chapter 17) and pass it to Pref::output:
 Pref::output(x -> (x, normal(x))):
 1 + x/(x + 1) - 2/x
      x  2       −2 x2 + x + 2
        − + 1, −
     x+1 x          x2 + x
The library generate contains functions for converting MuPAD expressions to the
input format of other programming languages (C, Fortran, or TEX). In the
following example, the MuPAD output is converted to a string. You might then
write this string to a text file for further processing with TEX:
                                                                                      13-3
13   Utilities
                  Pref::output(generate::TeX): diff(f(x),x)
                     ”\frac{\partial}{\partial x} f\!\left(x\right)”
                 The following command resets the output routine to its original state:
                  Pref::output(NIL):
                 After each computed result, the system now prints the string generated by the
                 procedure myInformation on the screen:
     13-4
                                                                 User-Defined Preferences
 factor(x^3 - 1)
             (          )
    (x − 1) · x + x2 + 1
You can reset a preference to its default value by specifying NIL as argument. For
example, the command Pref::report(NIL) resets the value of Pref::report to
0. Similarly, Pref(NIL) resets all preferences to their default values.
Exercise 13.1: The MuPAD function bytes returns the amount of logical and
physical memory used by the current MuPAD session. Let this information appear
on the screen after each output, using Pref::postOutput.
                                                                                     13-5
13   Utilities
                  This enables you to access intermediate results that have not been assigned to an
                  identifier. It is remarkable that the use of last may speed up certain interactive
                  evaluations when compared to the use of identifiers to store intermediate results.
                  In the following example, we first try to compute a definite integral symbolically.
                  After recognizing that MuPAD does not compute a symbolic value, we ask for a
                  floating-point approximation:
                   f := int(sin(x)*exp(x^3)+x^2*cos(exp(x)), x=0..1)
                      ∫     1
                                              3
                                x2 cos(ex ) + ex sin(x) dx
                        0
                   startingTime := time():
                   float(f);
                   (time() - startingTime)*msec
0.5356260737
750 msec
                  The function time returns the total computing time (in milliseconds) used by the
                  system since the beginning of the session. Thus the printed difference is the time
                  for computing the floating-point approximation.
     13-6
                                                                                     The History Mechanism
 startingTime := time():
 float(%2);
 (time() - startingTime)*msec
0.5356260737
40 msec
In this case, the reason for the gain in speed is that MuPAD does not re-evaluate
the objects that last(i), %i, or % refer to.1 Thus calls to last form an exception to
the usual complete evaluation at interactive level (Section 5.2):
 delete x: sin(x): x := 0: %2
      sin(x)
Please note that the value of last(i) may differ from the i-th but last visible
output if you have suppressed the screen output of some intermediate results by
terminating the corresponding commands with a colon. Also note that the value
of the expression last(i) changes permanently during a computation:
 1: last(1) + 1; last(1) + 1
      2
1 Note that this gain in speed is only achieved when working interactively, since identifiers are eval-
                                                                                                              13-7
13   Utilities
                 The environment variable HISTORY determines the number of results that MuPAD
                 stores in a session and that can be accessed via last:
                  HISTORY
                     20
                 This default means that MuPAD stores the previous 20 expressions. Of course you
                 can change this default by assigning a different value to HISTORY. This may be
                 appropriate when MuPAD has to handle huge objects (such as very large
                 matrices) that fill up a significant part of the main memory of your computer.
                 Copies of these objects are stored in the history table, requiring additional storage
                 space. In this case, you would reduce the memory load by choosing small values in
                 HISTORY. Note that HISTORY only yields the value of the interactive “history
                 depth.” Inside a procedure, last only accepts the arguments 1, 2 and 3.
                 We strongly recommend to use last only interactively. The use of last within
                 procedures is considered bad programming style and should be avoided.
     13-8
                                                                   Information on MuPAD® Algorithms
             As an example, we invert the following matrix (Section 4.15) over the ring of
             integers modulo 11:
              M := Dom::Matrix(Dom::IntegerMod(11)):
              A := M([[1, 2, 3], [2, 4, 7], [0, 7, 5]]):
              A^(-1)
               Info: using Gaussian elimination (LR decomposition)
                                                   
                     1 mod 11 0 mod 11 6 mod 11
                                             
                  3 mod 11 4 mod 11 8 mod 11 
                   9 mod 11 1 mod 11 0 mod 11
                                                                                              13-9
13   Utilities
                 If you enter
                  setuserinfo(Any, 0):
     13-10
                                                                      Restarting a MuPAD® Session
                                                                                             13-11
13   Utilities
                  You can neither use the output of such a command for further computation nor
                  save it to a file.2 system returns the error status of the operating system to the
                  MuPAD® session. When called with the ! syntax, the output of this value is
                  suppressed.
2 If this is desired, you can use another command of the operating system to write the output to a
file and read this file into a MuPAD session via import::readdata.
     13-12
                                                                        14
Type Specifiers
       The data structure of a MuPAD® object is its domain type, which can be requested
       by means of the function domtype. The domain type reflects the structure that the
       MuPAD kernel uses internally to manage the objects. The type concept also leads
       to a classification of the objects according to their mathematical meaning:
       numbers, sets, expressions, series expansions, polynomials, etc.
       In this section, we describe how to obtain detailed information about the
       mathematical structure of objects. For example, how can you find out efficiently
       whether an integer of domain type DOM_INT is positive or even, or whether all
       elements of a set are equations?
       Such type checks are barely relevant when using MuPAD interactively: you can
       control the mathematical meaning of an object by direct inspection. Type checks
       are mainly used for implementing mathematical algorithms, i.e., when
       programming MuPAD procedures (Chapter 17). For example, a procedure for
       differentiating expressions has to decide whether its input is a product, a
       composition of functions, a symbolic call of a known function, etc. Each case
       requires a different action, such as supplying the product rule, the chain rule, etc.
14   Type Specifiers
                      For expressions of domain type DOM_EXPR, the function type yields a finer
                      distinction according to the mathematical meaning of the expression: sums,
                      products, function calls, etc.:
                       type(a + b), type(a*b), type(a^b), type(a(b))
                          ”_plus”, ”_mult”, ”_power”, ”function”
                       type(a = b), type(a < b), type(a <= b)
                          ”_equal”, ”_less”, ”_leequal”
                      For most of these (with the exception of a(b)), the result returned by type is the
                      name of the function that generates the expression (internally, a symbolic sum or
                      product is represented by a call of the system functions _plus or _mult,
                      respectively). More generally, the result for most symbolic calls of system
                      functions is the identifier of the function as a string:
                       type(ln(x)), type(diff(f(x), x)), type(fact(x))
                          ”ln”, ”diff”, ”fact”
                      You can use both the domain types DOM_INT, DOM_EXPR, etc. and the strings
                      returned by type as type specifiers. There exists a variety of other type specifiers
                      in addition to the “standard typing” of MuPAD objects given by type. An example
                      is Type::Numeric. This type comprises all “numerical” objects (of domain type
                      DOM_INT, DOM_RAT, DOM_FLOAT, or DOM_COMPLEX).
     14-2
                                                             The Functions type and testtype
                                      i5/2 + i2 − i1/2 − 1
                     f (i) =
                               i5/2 + i2 + 2 i3/2 + 2 i + i1/2 + 1
How can MuPAD decide whether the set
 S := {f(i) $ i = -1000..-2} union {f(i) $ i=0..1000}:
contains only rational numbers? Hint: For a specific integer i, use the function
normal to simplify subexpressions of f(i) containing square roots.
Exercise 14.2: Consider the expressions sin(i π/200) with integer values of i
between 0 and 100. Which of them are simplified by the MuPAD sin function,
which are returned as symbolic values sin(·)?
                                                                                       14-3
14   Type Specifiers
     14-4
                                             Comfortable Type Checking: the Type Library
For example, the type specifier Type::PosInt represents the set of positive
integers n > 0, Type::NonNegInt corresponds to the nonnegative integers n ≥ 0,
Type::Even and Type::Odd represent the even and odd integers, respectively.
These type specifiers are of domain type Type:
 domtype(Type::Even)
    Type
You can use such type specifiers to query the mathematical structure of MuPAD
objects via testtype. In the following example, we extract all even integers from a
list of integers via select (Section 4.6):
 select([i $ i = 1..20], testtype, Type::Even)
    [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
                                                                                      14-5
14   Type Specifiers
                      Exercise 14.3: How can you compute the intersection of a set with the set of
                      positive integers?
                      Exercise 14.4: Use ?Type::ListOf to consult the help page for this type
                      constructor. Construct a type specifier corresponding to a list of two elements
                      such that each element is again a list with three arbitrary elements.
     14-6
                                                                        15
Loops
        The loop variable i automatically runs through the values 1, 2, 3, 4. For each value
        of i, all commands between do and end_for are executed. There may be
        arbitrarily many commands, separated by semicolons or colons. The system does
        not print the results computed in each loop iteration on the screen, even if you
        terminate the commands by semicolons. For that reason, we used the print
        command to generate an output in the above example.
15   Loops
             The following variant counts backwards. We use the tools from Section 4.11 to
             make the output look more appealing:
              for j from 4 downto 2 do
                 print(Unquoted,
                       "The square of ".expr2text(j)." is ".
                       expr2text(j^2))
              end_for:
                   The square of 4 is 16
The square of 3 is 9
The square of 2 is 4
             You can use the keyword step to increment or decrement the loop variable in
             bigger or smaller steps:
              for x from 3 to 8 step 2 do print(x, x^2) end_for:
                   3, 9
5, 25
7, 49
             Note that at the end of the iteration with x = 7 the value of x is incremented to 9.
             This exceeds the upper bound 8, and the loop terminates. Here is another variant
             of the for loop:
              for i in [5, 27, y] do print(i, i^2) end_for:
                   5, 25
27, 729
                          2
                   y, y
             The loop variable only runs through the values from the list [5, 27, y]. As you can
             see, such a list may contain symbolic elements such as the variable y .
     15-2
                                                                                             Loops
4, 16
16, 256
The system executes the commands between repeat and until repeatedly. The
loop terminates when the condition between until and end_repeat holds true. In
the above example, we have i = 4 and x = 16 at the end of the second step. Hence
the third step is executed, and afterwards we have i = 16, x = 256. Now the
termination condition x > 100 is satisfied and the loop terminates.
Another loop variant is the while loop:
 x := 2:
 while x <= 100 do
     i := x; x := i^2; print(i, x)
 end_while:
      2, 4
4, 16
16, 256
In a repeat loop, the system checks the termination condition after each loop
iteration. In a while loop, this condition is checked before each iteration. As soon
as the condition evaluates to FALSE, the system terminates the while loop.
                                                                                              15-3
15   Loops
             You can use break to abort a loop explicitly. Typically this is done within an if
             construction (Chapter 16):
              for i from 3 to 100 do
                  print(i);
                  if i^2 > 20 then break end_if
              end_for:
                     3
             After a call to next, the system skips all commands up to end_for. It returns
             immediately to the beginning of the loop and starts the next iteration with the
             next value of the loop variable:
              for i from 2 to 5 do
                  x := i;
                  if i > 3 then next end_if;
                  y := i;
                  print(x, y)
              end_for:
                     2, 2
3, 3
     15-4
                                                                                        Loops
We recall that every MuPAD command returns an object. For a loop, this is the
return value of the most recently executed command. If you do not terminate the
loop command with a colon as in all of the above examples, then MuPAD displays
this value:
 delete x: for i from 1 to 3 do x.i := i^2 end_for
    9
You may process this value further. In particular, you can assign it to an identifier
or use it as the return value of a MuPAD procedure (Chapter 17):
 factorial := proc(n)
   local result;
   begin
     result := 1;
     for i from 2 to n do
       result := result * i
     end_for
   end_proc:
The return value of the above procedure is the return value of the for loop, which
in turn is the value of the last assignment to result.
Internally, loops are system function calls. For example, MuPAD processes a for
loop by evaluating the function _for:
 _for(i, first_i, last_i, increment, command):
This is equivalent to
 for i from first_i to last_i step increment do
     command
 end_for:
                                                                                         15-5
                                                                    16
"3 is prime"
       Here, the primality test isprime(i) returns either TRUE or FALSE. If the value is
       TRUE, the system executes the commands between then and else (in this case,
       only one print command). If it is FALSE, the commands between else and end_if
       are executed. The else branch is optional:
        for i from 2 to 4 do
          if isprime(i)
             then text := expr2text(i)." is prime";
                  print(text)
          end_if
        end_for:
            "2 is prime"
            "3 is prime"
16   Branching: if-then-else and case
                         Here, the then branch comprises two commands separated by a semicolon (or,
                         alternatively, a colon). You may nest commands, loops, and branching statements
                         arbitrarily:
                          primes := []: evenNumbers := []:
                          for i from 30 to 50 do
                            if isprime(i)
                               then primes := primes.[i]
                               else if testtype(i,Type::Even)
                                       then evenNumbers := evenNumbers.[i]
                                    end_if
                            end_if
                          end_for:
                         You can create more complex conditions for the if statement by using the
                         Boolean operators and, or, and not (Section 4.10). The following for loop prints
                         all prime twins [i, i + 2] with i ≤ 100. The alternative condition not (i>3) yields
                         the additional pair [2, 4]:
                          for i from 2 to 100 do
                            if (isprime(i) and isprime(i+2)) or not (i>3)
                               then print([i,i+2])
                            end_if
                          end_for:
                                                              [2, 4]
[3, 5]
[5, 7]
...
     16-2
                                                              Branching: if-then-else and case
is equivalent to
 if condition then command1 else command2 end_if:
The return value of an if statement is, as for any MuPAD procedure, the result of
the last executed command:1
 x := -2: if x > 0 then x else -x end_if
     2
For example, you can use the arrow operator -> (Section 4.12) to implement the
absolute value of numbers as follows:
 Abs := y -> (if y > 0 then y else -y end_if):
 Abs(-2), Abs(-2/3), Abs(3.5)
            2
     2,       , 3.5
            3
As you can see, you can use if commands both at the interactive level and within
procedures. The typical application is in programming MuPAD procedures, where
if statements and loops control the flow of the algorithm. A simple example is the
above function Abs. You find more examples in Chapter 17.
If you have several nested if … else if … constructions, you can abbreviate this by
using the elif statement:
 if condition1 then
   statements1
 elif condition2 then
   statements2
 elif ...
 else
   statements
 end_if:
                                                                                         16-3
16   Branching: if-then-else and case
                         A typical application is for type checking within procedures (Chapter 17). The
                         following version of Abs computes the absolute value if the input is an integer, a
                         rational number, a real floating-point number, or a complex numbera. Otherwise,
                         it raises an error:
                          Abs := proc(y) begin
                            if (domtype(y) = DOM_INT) or (domtype(y) = DOM_RAT)
                               or (domtype(y) = DOM_FLOAT) then
                                 if y > 0 then y else -y end_if;
                            elif (domtype(y) = DOM_COMPLEX) then
                                 sqrt(Re(y)^2 + Im(y)^2);
                            else "Invalid argument type" end_if:
                          end_proc:
                          delete x: Abs(-3), Abs(5.0), Abs(1+2*I), Abs(x)
                                       √
                             3, 5.0,    5, ”Invalid argument type”
     16-4
                                                      Branching: if-then-else and case
The keywords case and end_case indicate the beginning and the end of the
statement, respectively. MuPAD evaluates the expression after case. If the result
matches one of the expressions between of and do, the system executes all
commands from the first matching of on until it encounters either a break or the
keyword end_case.
Warning: Note that, if no break statement used in a branch, the following
branches are entered and executed, too. This is in the same style as the switch
statement in the C programming language. It allows several branches to share the
same code.
If none of the of branches applies and there is an otherwise branch, the code
between otherwise and end_case is executed. The return value of a case
statement is the value of the last executed command. We refer to the
corresponding help page ?case for a more detailed description.
                                                                                    16-5
16   Branching: if-then-else and case
                          _case(domtype(y),
                                DOM_INT, NIL,
                                DOM_RAT, NIL,
                                DOM_FLOAT,
                                  (if y > 0 then y else -y end_if; break),
                                DOM_COMPLEX, (sqrt(Re(y)^2 + Im(y)^2); break),
                                "Invalid argument type"):
     16-6
                                                                      17
MuPAD® Procedures
                         a MuPAD session via read (page 12-5) or with the entry ‘Read commands …’ from
                         the ‘Notebook’ menu. Apart from the evaluation level, the MuPAD kernel
                         processes the commands in the file exactly in the same way as if they were entered
                         interactively. MuPAD includes an editor with syntax highlighting for MuPAD
                         programs.
     17-2
                                                                                                   Defining Procedures
Defining Procedures
             The following function, which compares two numbers and returns their
             maximum, is an example of a procedure definition via proc … end_proc:
              maximum := proc(a, b) /* comment: maximum of a and b */
                         begin
                           if a<b then return(b) else return(a) end_if;
                         end_proc:
             The text enclosed between /* and */ is a comment1 and completely ignored by the
             system. This is a useful tool for documenting the source code when you write the
             procedure definition in a text file.
             The above sample procedure contains an if statement as the only command.
             More realistic procedures contain many commands (separated by colons or
             semicolons). The command return terminates a procedure and passes its
             argument as output value to the system.
             A MuPAD® object generated via proc … end_proc is of domain type DOM_PROC:
              domtype(maximum)
                  DOM_PROC
             You can decompose and manipulate a procedure like any other MuPAD object. In
             particular, you may assign it to an identifier, as above. The syntax of the function
             call is the same as for other MuPAD functions:
              maximum(3/7, 0.4)
                   3
                   7
1 Alternatively, you can start a comment by //. A comment started with // automatically ends at the
                                                                                                                       17-3
17   MuPAD® Procedures
                         The favorite example for a recursive algorithm is the computation of the factorial
                         n! = 1 · 2 · · · · · n of a nonnegative integer, which may be defined by the rule
                         n! = n · (n − 1)! together with the initial condition 0! = 1. The realization as a
                         recursive procedure might look as follows:
                          factorial := proc(n) begin
                            if n = 0 then
                                 return(1)
                            else return(n*factorial(n - 1))
                            end_if
                          end_proc:
                          factorial(10)
                             3628800
     17-4
                                                                                   The Return Value of a Procedure
              The if statement returns either 1 or n (n − 1)! . Since the end of the procedure is
              reached directly after the if statement, this is the return value of the call
              factorial(n).
              For n = 0, MuPAD® does not execute the last statement (the recursive call of
              n * factorial(n - 1)) after returning 1. For n ̸= 0, the most recently computed
              value is n * factorial(n - 1), which is then the return value of the call
              factorial(n).
                                                                                                             17-5
17   MuPAD® Procedures
     17-6
                                                                     Returning Symbolic Function Calls
              You achieve the same behavior in your own procedures when you encapsulate the
              procedure name in a hold upon return. The hold (page 5-4) prevents the function
              from calling itself recursively and ending up in an infinite recursion. The
              following function computes the absolute value for numerical inputs (integers,
              rational numbers, real floating-point numbers, and complex numbers). For all
              other kinds of inputs, it returns itself symbolically:
               Abs := proc(x) begin
                 if testtype(x, Type::Numeric) then
                    if domtype(x) = DOM_COMPLEX then
                         return(sqrt(Re(x)^2 + Im(x)^2))
                    else if x >= 0 then
                              return(x)
                         else return(-x)
                         end_if
                    end_if
                 end_if;
                 hold(Abs)(x)
               end_proc:
               Abs(-1), Abs(-2/3), Abs(1.234), Abs(2 + I/3),
               Abs(x + 1)
                                    √
                       2             37
                  1,     , 1.234,       , Abs(x + 1)
                       3             3
                                                                                                 17-7
17   MuPAD® Procedures
                         A more elegant way is to use the MuPAD® object procname, which returns the
                         name of the calling procedure:
                          Abs := proc(x) begin
                            if testtype(x, Type::Numeric) then
                               if domtype(x) = DOM_COMPLEX then
                                    return(sqrt(Re(x)^2 + Im(x)^2))
                               else if x >= 0 then
                                         return(x)
                                    else return(-x)
                                    end_if
                               end_if
                            end_if;
                            procname(args())
                          end_proc:
                          Abs(-1), Abs(-2/3), Abs(1.234), Abs(2 + I/3),
                          Abs(x + 1)
                                               √
                                  2             37
                             1,     , 1.234,       , Abs(x + 1)
                                  3             3
                         Here, we use the expression args(), which returns the sequence of arguments
                         passed to the procedure (cf. page 17-21).
     17-8
                                                                             Local and Global Variables
              The procedure f modifies the value of a, which has been set outside the
              procedure. When the procedure terminates, a has a new value, which is again
              changed by further calls to f.
              The keyword local declares identifiers as local variables that are only valid
              within the procedure:
               a := b: f := proc() local a; begin a := 2 end_proc:
               f(): a
                  b
              Despite the equal names, the assignment a:= 2 of the local variable does not affect
              the value of the global identifier a that has been defined outside the procedure.
              You can declare an arbitrary number of local variables by specifying a sequence of
              identifiers after local:
               f := proc(x, y, z)
                    local A, B, C;
                    begin
                       A:= 1; B:= 2; C:= 3; A*B*C*(x + y + z)
                    end_proc:
               f(A, B, C)
                  6A + 6B + 6C
                                                                                                    17-9
17   MuPAD® Procedures
                         Local variables of a procedure have a special domain type DOM_VAR. They do not
                         get mixed up with global variables which are identifiers of type DOM_IDENT. Note
                         that also local variables declared by the same name in the source code of different
                         functions have no reference to one another. Also, when calling a function several
                         times, a local variable refers to a different value in each call:
                          f := proc(x) local a, b;
                          begin
                            a := x;
                            if x > 0 then b := f(x - 1);
                            else          b := 1;
                            end_if;
                            print(a, x);
                            b + a;
                          end:
                          f(2)
                             0, 0
1, 1
2, 2
                         Moreover, a procedure call can change the calling environment in a subtle way by
                         redefining global variables (“side effect”). In more complex programs, this may
                         lead to unwanted effects that are difficult to debug.
     17-10
                                                                              Local and Global Variables
The reason for the error is that MuPAD cannot add the value NIL of the local
variable to the number 1.
We now present a realistic example of a meaningful procedure. If we use arrays of
domain type DOM_ARRAY to represent matrices, we are faced with the problem that
there is no direct way to perform matrix multiplication with such arrays.3 The
following procedure solves this problem: you can compute the matrix product
C = A · B with the command C:= MatrixProduct(A, B). We want the procedure to
work for arbitrary dimensions of the matrices A and B , provided the result is
defined mathematically. If A is an m × n matrix, then B may be an n × r matrix,
where m, n, r are arbitrary positive integers. The result is the m × r matrix C with
the entries
                        ∑n
                  Cij =     Aik Bkj , i = 1, . . . , m, j = 1, . . . , r.
                             k=1
The multiplication procedure below automatically extracts the dimension
parameters m, n, r from the arguments, namely from the 0-th operands of the
input arrays (page 4-44). If B is a q × r matrix with q ̸= n, the multiplication is not
defined mathematically. In this case, the procedure terminates with an error
3 If you use the data type Dom::Matrix() instead, you can directly use the standard operators +, -,
                                                                                                           17-11
17   MuPAD® Procedures
                         message. For that purpose, we employ the function error, which aborts the
                         calling procedure and writes the string passed as argument on the screen. We
                         store the result component by component in the local variable C. We initialize this
                         variable as an array of dimension m × r, so that the result of our procedure is of
                         the desired data type DOM_ARRAY. We might implement the sum over k in the
                         computation of Cij as a loop of the form for k from 1 to n do .. Instead, we
                         use the system function _plus which returns the sum of its arguments. We
                         generally recommend to use these system functions, if possible, since they work
                         quite efficiently. The return value of MatrixProduct is the final expression C:
                          MatrixProduct := /* multiplication C=AB of an m x n           */
                          proc(A, B)       /* matrix A by an n x r Matrix B             */
                          local m, n, r, i, j, k, C; /* with arrays A, B of             */
                          begin                       /* domain type DOM_ARRAY          */
                              m := op(A, [0, 2, 2]);
                              n := op(A, [0, 3, 2]);
                              if n <> op(B, [0, 2, 2]) then
                                error("incompatible matrix dimensions")
                              end_if;
                              r := op(B, [0, 3, 2]);
                              C := array(1..m, 1..r);        /* initialization          */
                                for i from 1 to m do
                                  for j from 1 to r do
                                    C[i, j] := _plus(A[i, k]*B[k, j] $ k = 1..n)
                                  end_for
                                end_for;
                                C
                            end_proc:
                         A general remark about MuPAD programming style: you should always perform
                         argument checking in procedures meant for interactive use. If you implement a
                         procedure, you usually know which types of inputs are valid (such as DOM_ARRAY in
                         the above example). If somebody passes parameters of the wrong type by mistake,
                         this usually leads to system functions calls with invalid arguments, and your
                         procedure aborts with an error message originating from a system function. In the
                         above example, the function op returns the value FAIL when accessing the 0-th
                         operand of A or B and one of them is not of type DOM_ARRAY. Then this value is
                         assigned to m, n or r, and the following for loop aborts with an error message,
                         since FAIL is not allowed as a value for the endpoint of the loop.
     17-12
                                                                 Local and Global Variables
In such a situation, it is often difficult to locate the source of the error. However,
an even worse scenario might happen: if the procedure does not abort, the result
is likely to be wrong! Thus, type checking helps to avoid errors.
In the above example, we might add a type check of the form
 if domtype(A) <> DOM_ARRAY or domtype(B) <> DOM_ARRAY
   then error("arguments must be of type DOM_ARRAY")
 end_if
to the procedure body. Starting on page 17-20, we discuss a simpler type checking
concept.
                                                                                         17-13
17   MuPAD® Procedures
     Subprocedures
                         Often tasks occur frequently within a procedure and you want to implement them
                         again in the form of a procedure. This structures and simplifies the program code.
                         In many cases, such a procedure is used only from within a single procedure.
                         Then it is reasonable to define this procedure locally as a subprocedure only in the
                         scope of the calling procedure. In MuPAD® you can use local variables to
                         implement subprocedures. If you want to make
                          g := proc() begin ... end_proc:
                         a local procedure of
                          f := proc() begin ... end_proc:
                         define f as follows:
                          f := proc()
                          local g;
                          begin
                            g := proc() begin ... end_proc;           /* subprocedure */
                         Now, g is a local procedure of f and you can use it only from within f.
                         We give an example. You can implement matrix multiplication by means of
                         suitable column×row multiplications:
                                                              ( )          ( )
                                                                4            6
                                 (     ) (     )  (2, 1) ·        (2, 1) ·         (       )
                                   2 1     4 6                 2            3 
                                                                                     10 15
                                        ·         =           ( )          ( ) =            .
                                   5 3     2 3                 4            6       26 39
                                                      (5, 3) ·     (5, 3) ·
                                                                2            3
     17-14
                                                                       Subprocedures
We now write a procedure MatrixMult that expects input arrays A and B of the
form array(1..m, 1..k) and array(1..k, 1..n), and returns the m × n matrix
product A · B . A call of the subprocedure RowTimesColumn with arguments i, j
extracts the i-th row and the j -th column from the input matrices A and B ,
respectively, and computes the inner product of the row and the column. The
subprocedure uses the arrays A, B as well as the locally declared dimension
parameters m, n, and k as “global” variables:
 MatrixMult := proc(A, B)
 local m, n, k, K,     /* local variables */
       RowTimesColumn; /* local subprocedure */
 begin
   /* subprocedure */
   RowTimesColumn := proc(i, j)
   local row, column, r;
   begin
     /* ith row of A: */
     row := array(1..k, [A[i,r] $ r=1..k]);
     /* jth column of B: */
     column := array(1..k, [B[r,j] $ r=1..k]);
     /* row times column */
     _plus(row[r]*column[r] $ r=1..k)
   end_proc;
   if k <> K then
      error("# of columns of A <> # of rows of B")
   end_if;
   /* matrix A*B: */
   array(1..m, 1..n,
         [[RowTimesColumn(i, j) $ j=1..n] $ i=1..m])
 end_proc:
                                                                                17-15
17   MuPAD® Procedures
     17-16
                                                                                      Scope of Variables
Scope of Variables
              The MuPAD® programming language implements lexical scoping. This
              essentially means that the scope of a procedure’s local variables and parameters
              can already be determined when the procedure is defined. We start with a simple
              example to explain this concept.
               p := proc() begin x end_proc:
               x := 3: p(); x := 4: p()
                  3
                  4
               q := proc() local x; begin x := 5; p(); end_proc:
               q()
                  4
                                                                                                      17-17
17   MuPAD® Procedures
                         The previously defined global procedure p is not accessed from within q because a
                         local variable p is declared. The call of the local procedure p from within q now
                         indeed returns the current value of the local variable x, as shown by the call q().
                         The last command p(), however, executes the global procedure p defined before,
                         which still returns the current value 4 of the global variable x.
                         Here is another example:
                          p := proc(x) begin 2 * cos(x) + 1; end_proc:
                          q := proc(y)
                              local cos;
                            begin
                              cos := proc(z) begin z + 1; end_proc;
                              p(y) * cos(y)
                            end_proc:
                          p(PI), q(PI)
                             −1, −π − 1
     17-18
                                      Scope of Variables
2, 3
5, 4, 6
                                                  17-19
17   MuPAD® Procedures
     Type Declaration
                         MuPAD® provides easy-to-use type checking for procedure arguments. For
                         example, you can restrict the arguments of MatrixProduct, a procedure from the
                         Section starting on page 17-9, to the domain type DOM_ARRAY as follows:
                          MatrixProduct := proc(A: DOM_ARRAY, B: DOM_ARRAY)
                                             local m, n, r, i, j, k, C;
                                           begin ...
                         If you declare the type of the parameters of a procedure in the form used above,
                         argument: typeSpecifier, a call of the procedure with parameters of an
                         incompatible type leads to an error message. In the example above, we used the
                         domain type DOM_ARRAY as a type specifier.
                         We have discussed MuPAD’s type concept in Chapter 14. The Type library offers
                         Type::NonNegInt to represent the set of nonnegative integers. If we use it in the
                         following variant of the factorial function
                          factorial := proc(n: Type::NonNegInt) begin
                            if n = 0 then
                                 return(1)
                            else n*factorial(n - 1)
                            end_if
                          end_proc:
     17-20
                                                     Procedures with a Variable Number of Arguments
             You can implement this behavior in your own procedures as well. The function
             args returns the arguments passed to the calling procedure:
             The following function simulates the behavior of the system function max:
              maximum := proc() local m, i; begin
                m := args(1);
                for i from 2 to args(0) do
                  if m < args(i) then m := args(i) end_if
                end_for:
                m
              end_proc:
              maximum(1), maximum(3/7, 9/20), maximum(-1, 3, 0, 7, 3/2, 7.5)
                      9
                 1,      , 7.5
                      20
             Here, we initialize m with the first argument. Then, we test for each of the
             remaining arguments whether it is greater than m, and if so, replace m by the
             corresponding argument. Thus, m contains the maximum at the end of the loop.
             Note that if you call maximum with only one argument (so that args(0) = 1), then
             the loop for i from 2 to 1 do ... is not executed at all.
                                                                                                17-21
17   MuPAD® Procedures
                         You may use both formal parameters and accesses via args in a procedure:
                          f := proc(x, y) begin
                                 if args(0) = 3 then
                                      x^2 + y^3 + args(3)^4
                                 else x^2 + y^3
                                 end_if
                               end_proc:
                          f(a, b), f(a, b, c)
                             a2 + b3 , a2 + b3 + c4
                         The following example is a trivial function returning itself symbolically for any
                         number of arguments that are actually passed:
                          f := proc() begin procname(args()) end_proc:
                          f(1), f(1, 2), f(1, 2, 3), f(a1, b2, c3, d4)
                             f (1) , f (1, 2) , f (1, 2, 3) , f (a1, b2, c3, d4)
     17-22
                                                                              Options: the Remember Table
Fn = Fn−1 + Fn−2 , F0 = 0, F1 = 1.
             This way of computing Fn is highly inefficient for larger values of n. To see why,
             let us trace the recursive calls of F when computing F4 . You may regard this as a
             tree structure: F(4) calls F(3) and F(2), F(3) calls F(2) and F(1) etc.:
F4
F3 F2
F2 F1 F1 F0
F1 F0
             One can show that the call F(n) leads to about 1.45.. · (1.618..)n calls of F for large
             n. These “costs” grow dramatically fast for increasing values of n:
              time(F(10)), time(F(15)), time(F(20)), time(F(25))
                  80, 910, 10290, 113600
                                                                                                       17-23
17   MuPAD® Procedures
                         We recall that the function time returns the time in milliseconds used to evaluate
                         its argument.
                         We see that many calls (such as, for example, F(1)) are executed several times.
                         For evaluating F(4), it is sufficient to execute only the boxed function calls
                         F(0), ..., F(4) in the above figure and to store these values. All other
                         computations of F(0), F(1), F(2) are redundant since their results are already
                         known. This is precisely what MuPAD does when you declare F with the option
                         remember:
                          F := proc(n: Type::NonNegInt)
                                 option remember;
                               begin
                                 if n < 2 then n
                                 else F(n - 1) + F(n - 2) end_if
                               end_proc:
                         The system internally creates a remember table for the procedure F, which
                         initially is empty. At each call to F, MuPAD checks whether there is an entry for
                         the current argument sequence in this table. If this is the case, the procedure is
                         not executed at all, and the result is taken from the table. If the current arguments
                         do not appear in the table, the system executes the procedure body as usual and
                         returns its result. Then it appends the argument sequence and the return value to
                         the remember table. This ensures that a procedure is not unnecessarily executed
                         twice with the same arguments.
                         In the Fibonacci example, the call F(n) now leads to only n + 1 calls to compute
                         F(0), ..., F(n). In addition, the system searches the remember table n − 2 times.
                         However, this happens very quickly. In this example, the benefit in speed from
                         using option remember is quite dramatic:
                          time(F(10)), time(F(15)), time(F(20)), time(F(25)),
                          time(F(500))
                             0, 10, 0, 10, 390
                         The real running times are so small that the system cannot measure them exactly.
                         This explains the (rounded) times of 0 milliseconds for F(10) and F(20).
     17-24
                                                                        Options: the Remember Table
Of course, you can implement this method for computing the Fibonacci numbers
directly by computing Fn iteratively instead of recursively and storing already
computed values in a table:4
 F := proc(n: Type::NonNegInt)
        local i, F;
      begin
        F[0] := 0: F[1] := 1:
        for i from 2 to n do
          F[i] := F[i - 1] + F[i - 2]
        end_for
      end_proc:
 time(F(10)), time(F(15)), time(F(20)), time(F(25)),
 time(F(500))
     10, 0, 10, 0, 400
The function numlib::fibonacci from the number theory library is yet faster for
large arguments, since it uses more elaborate algorithms and direct formulas.
Warning: The remember mechanism recognizes only previously processed
inputs, but does not consider the values of possibly used global variables. When
the values of these global variables change, then the remembered return values
are usually wrong. In particular, this is the case for global environment variables
such as DIGITS:
 floatexp := proc(x) option remember;
             begin float(exp(x)) end_proc:
 DIGITS := 20: floatexp(1);
     2.7182818284590452354
 DIGITS := 40: floatexp(1); float(exp(1))
     2.718281828459045235360287471344923927842
2.718281828459045235360287471352662497757
Here, the system outputs the remembered value of floatexp(1) with higher
precision after switching from 20 to 40 DIGITS. Nevertheless, this is still the value
computed with DIGITS = 20; the output only shows all digits that were used
4 This procedure is not properly implemented: what happens when you call F(0)?
                                                                                             17-25
17   MuPAD® Procedures
                         internally5 in this computation. The last of the three numbers is the true value of
                         exp(1) computed with 40 digits. It differs from the wrongly remembered value at
                         the 30-th decimal digit.
                         You can explicitly add new entries to the remember table of a procedure. In the
                         following example, f is the function x 7→ sin(x)/x, which has a removable
                         singularity at x = 0. The limit is f (0) := limx→0 sin(x)/x = 1:
                          f := proc(x) begin sin(x)/x end_proc: f(0)
                             Error: Division by zero;
                             during evaluation of 'f'
                         The assignment f(0):= 1 creates a remember table for f, so that a later call of
                         f(0) does not try to evaluate the value of sin(x)/x for x = 0. Now you can use f
                         without running into danger at x = 0.
                         does not generate the function f : x 7→ x2 , but rather creates a remember table for
                         the identifier f with the entry x^2 only for the symbolic identifier x. Any other call
                         to f returns a symbolic function call:
                          f(x), f(y), f(1)
                               x2 , f (y) , f (1)
5 Internally, MuPAD uses a certain number of additional “guard digits” exceeding the number of
                         digits requested via DIGITS. However, for the output, the system truncates the internally computed value
                         to the requested number of digits.
     17-26
                                                                                    Input Parameters
Input Parameters
             The declared formal arguments of a procedure can be used like additional local
             variables:
              f := proc(a, b) begin a := 1; a + b end_proc:
              a := 2: f(a, 1): a
                   2
             Modifying a within this procedure does not affect the identifier a that is used
             outside the procedure. You should be cautious when you access the calling
             arguments via args (page 17-21) in a procedure after changing some input
             parameter. Assignment to a formal parameter changes the return value of args:
              f := proc(a) begin a := 1; a, args(1) end_proc: f(2)
                   1, 1
                                                                                               17-27
17   MuPAD® Procedures
     17-28
                                                                             Evaluation Within Procedures
              In contrast, within procedures, the system performs evaluation not completely but
              only with evaluation depth 1. This is similar to internally replacing each identifier
              by level(identifier, 1): every identifier is replaced by its value, but not
              recursively. We recall from page 5-1 the distinction between the value of an
              identifier (the evaluation at the time of assignment) and its evaluation (the
              “current value,” where symbolic identifiers that have been assigned a value in the
              meantime are replaced by their values as well). In interactive mode, calling an
              object yields its complete evaluation, while in procedures only the object’s value is
              returned. This explains the difference between the interactive result above and
              the following result:
               f := proc() begin
                      delete a, b, c:
                      x := a + b: a := b + 1: b := c:
                      x
                    end_proc:
               f()
                   a+b
              The reason why two different behaviors are implemented is that the strategy of
              incomplete evaluation makes the evaluation of procedures faster and increases
              the efficiency of MuPAD procedures considerably. For a beginner in
              programming MuPAD procedures, this evaluation concept has its pitfalls.
              However, after some practice you acquire an appropriate programming style so
              that you can work with the restricted evaluation depth without problems.
                                                                                                      17-29
17   MuPAD® Procedures
                         Warning: If you do not work interactively with MuPAD, but use an editor to
                         write your MuPAD commands into a text file which is read into a MuPAD session
                         via read (page 12-5), these commands are executed within a procedure (namely,
                         read). Consequently, the evaluation depth is 1.
                         You can use the system function level (page 5-4) to control the evaluation depth
                         and to enforce complete evaluation if necessary:
                          f := proc() begin
                                 delete a, b, c:
                                 x := a + b: a := b + 1: b := c:
                                 level(x)
                               end_proc:
                          f()
                             2c + 1
                         You can pass the name of the integration variable as additional argument to the
                         procedure. Thus, the following variants are valid:
                          f := proc(n, x) begin int(exp(x^n), x) end_proc:
                          f := proc(n, x) local y; begin
                               y := x; int(exp(y^n), y) end_proc:
                         If you need symbolic identifiers for intermediate results, you can generate an
                         identifier without a value via genident() (page 4-8) and assign it to a local
                         variable.
     17-30
                                                                                Function Environments
Function Environments
             MuPAD® provides a variety of tools for handling built-in mathematical standard
             functions such as sin, cos, exp. These tools implement the mathematical
             properties of these functions. Typical examples are the float conversion routine,
             the differentiation function diff, or the function expand, which you use to
             manipulate expressions:
              float(sin(1)), diff(sin(x), x, x, x),
              expand(sin(x + 1))
                 0.8414709848, − cos(x) , cos(1) sin(x) + sin(1) cos(x)
             immediately yields the desired answer. However, often there are situations where
             the newly implemented function cannot be composed from standard objects.
             Thus, our goal is to hand the rules of manipulation (floating-point approximation,
             differentiation etc.) for symbolic function calls to the MuPAD functions float,
             diff etc. This is the actual challenge when you “implement a new mathematical
             function in MuPAD:” to distribute the knowledge about the mathematical
             meaning of the symbol to MuPAD’s standard tools. Indeed, this is a necessary
             task: for example, if you want to differentiate a more complex expression
             containing both the new function and some standard functions, then this is only
                                                                                                  17-31
17   MuPAD® Procedures
                         possible via the system’s differentiation routine. Thus, the latter has to learn how
                         to handle the new symbols.
                         For that purpose, MuPAD provides the domain type DOM_FUNC_ENV (short for:
                         function environment). Indeed, all built-in mathematical standard functions are
                         of this type in order to enable float, diff, expand etc. to handle them:
                          domtype(sin)
                             DOM_FUNC_ENV
                         You can call a function environment like any “normal” function or procedure:
                          sin(1.7)
                             0.9916648105
                         You can look at the procedure for evaluating a function call with the function
                         expose, just like for normal functions:
                          expose(sin)
                            proc(x)
                              name sin;
                              local f, y;
                              option noDebug;
                            begin
                              if args(0) = 0 then
                                error("no arguments given")
                              else
                              ...
                            end_proc
                         To keep the example manageable, we will choose two closely related functions and
                         act as if they were not implemented in MuPAD yet. Our example functions are the
                         complete elliptic integral functions of the first and second kind, K(z) and E(z).
                         Since MuPAD already has a predefined identifier E, we will implement these
                         functions as ellipE and, for consistency, ellipK. (The more obvious names
     17-32
                                                                     Function Environments
ellipticE and ellipticK are already used by the MuPAD versions of the same
functions.) These functions appear in such different contexts as calculating the
perimeter of an ellipsis, the gravitational or electrostatic potential of a uniform
ring or the probability that a random walk in three dimensions ever goes through
the origin. For this presentation, let us concentrate on the following properties of
the functions E and K :
                                       E(z) − K(z)
                             E ′ (z) =             ,
                                           2z
                                       E(z) − (1 − z)K(z)
                             K ′ (z) =                    ,
                                           2 (1 − z)z
                                          π
                      E(0) = K(0) =         ,    E(1) = 1,
                                          2
                        (1)                               ( )2
                                    8 π 3/2             Γ 14
                    K          =    ( )2 ,      K(−1) = √ .
                         2         Γ − 14               4 2π
That is, we are going to implement the derivatives of E and K with the above
relations and make the functions evaluate at special points. Additionally, we will
implement the functions in such a way that they are written as E and K in the
output.
The basic functions are easy to write:
 ellipE :=
  proc(x) begin
    if x = 0 then PI/2
    elif x = 1 then 1
    else procname(x) end_if
  end_proc:
 ellipK :=
  proc(x) begin
    if x = 0 then PI/2
    elif x = 1/2 then 8*PI^(3/2)/gamma(-1/4)^2
    elif x = -1 then gamma(1/4)^2/4/sqrt(2*PI)
    else procname(x) end_if
  end_proc:
                                                                                       17-33
17   MuPAD® Procedures
                         Since the values of the functions are known only at specific places, we use
                         procname (page 17-7) to return the symbolic expressions ellipE(x) and
                         ellipK(x), respectively, for all arguments where the function values are not
                         known. This yields:
                          ellipE(0), ellipE(1/2),
                          ellipK(12/17), ellipK(x^2+1)
                                          ( )          ( )
                               π           1            12         (       )
                                 , ellipE     , ellipK     , ellipK x2 + 1
                               2           2            17
6 Note that you should avoid returning strings from such procedures. Using strings breaks both
     17-34
                                                                   Function Environments
form ellipK(x) and ellipE(x). In the example above, we did not provide any
such function attributes. Hence, the system functions do not yet know how to
proceed and, by default, return the expression or themselves symbolically:
 float(ellipE(1/3)), expand(ellipE(x + y)),
 diff(ellipE(x), x), diff(ellipK(x), x)
      ( )
       1               ∂         ∂
    E     , E(x + y) ,    E(x) ,    K(x)
       3               ∂x        ∂x
By assigning to the "diff" slot of our function environments, we set the attributes
for the differentiation routine diff:
 ellipE::diff :=
  proc(f,x)
   local z;
  begin
   z := op(f);
   (ellipE(z) - ellipK(z))/(2*z) * diff(z, x)
  end_proc:
 ellipK::diff :=
  proc(f,x)
   local z;
  begin
   z := op(f);
   (ellipE(z) - (1-z)*ellipK(z))/
      (2*(1-z)*z) * diff(z, x)
  end_proc:
These commands tell diff that diff(f, x) with a symbolic function call
f = ellipE(z), where z depends on x, should apply the procedure assigned to
ellipE::diff. The well-known chain rule yields
                               d                 dz
                                  E(z) = E ′ (z)    .
                               dx                dx
The specified procedure implements this rule, where the inner function in the
expression f = ellipE(z) is given by z = op(f).
                                                                                      17-35
17   MuPAD® Procedures
                         As far as diff is concerned, the implementation of our two elliptic integrals is now
                         complete:
                          diff(ellipE(x), x, x)
                              E(x)−K(x)         E(x)+K(x) (x−1)
                                  2x        +       2 x (x−1)         E(x) − K(x)
                                                                  −
                                                2x                        2 x2
                          normal(diff(ellipK(2*x + 3), x, x, x))
                            - (73 E(2 x + 3) + 86 K(2 x + 3) + 115 x E(2 x + 3) +
                                                                      2
                                228 x K(2 x + 3) + 46 x                       E(2 x + 3) +
                                        2                                 3
                                202 x       K(2 x + 3) + 60 x                 K(2 x + 3)) /
                                        6              5              4                  3              2
                                (32 x       + 240 x        + 744 x            + 1220 x       + 1116 x       +
540 x + 108)
                         As an application, we now want MuPAD to compute the first terms of the Taylor
                         expansion of the complete elliptic integral of the first kind around x = 0. We can
                         use the function taylor since it calls diff internally:
                          taylor(ellipK(x), x = 0, 6)
                              π π x 9 π x2   25 π x3   1225 π x4   3969 π x5    ( )
                                +   +      +         +           +           + O x6
                              2   8   128     512       32768       131072
     17-36
                                                                     Function Environments
But there is more: With functions such as the elliptic integrals, which appear in
their own derivatives, the integration routine has a good chance of finding
symbolic integrals once the diff attributes have been implemented:
 int(ellipE(x), x)
                           (                   )
     2 E(x) 2 K(x)             2 E(x) 2 K(x)
           −       +x                +
        3      3                  3      3
Exercise 17.1: Extend the definitions of ellipE and ellipK by a "float" slot.
Use hypergeom::float and the following equivalences:
                                           ([       ]           )
                             π                  1 1
                  E(z) =       hypergeom      − ,      , [1], z
                             2                  2 2
                                           ([     ]          )
                             π                1 1
                  K(z) =       hypergeom       ,    , [1], z
                             2                2 2
Also, extend the definitions of the functions such that your new float evaluation is
automatically used when a floating point value is given as input.
                                   d |y|   |y| dy
                                         =        .
                                   dx       y dx
Set the "diff" attribute accordingly and compute the derivative of Abs(x^3).
Compare your result to the corresponding derivative of the system function abs.
                                                                                       17-37
17   MuPAD® Procedures
                               df
                         (1)      = 0, if f does not depend on x,
                               dx
                               dx
                         (2)      = 1,
                               dx
                               d(f + g)   df   dg
                         (3)            =    +            (linearity),
                                  dx      dx dx
                               da b   da     db
                         (4)        =    b+a            (product rule),
                               dx     dx     dx
                               d ab   d b ln(a)            d
                         (5)        =    e      = eb ln(a)    (b ln(a))
                               dx     dx                   dx
                                            db          da
                               = ab ln(a)      + ab−1 b    ,
                                            dx          dx
                               d                     dy
                         (6)      F (y(x)) = F ′ (y)         (chain rule).
                               dx                    dx
                         Moreover, for some functions F , the derivative is known, and we want to take this
                         into account in our implementation. For an unknown function F , we return the
                         symbolic function call of the differentiation routine.
     17-38
                                                 A Programming Example: Differentiation
The procedure Diff in Table 17.1 implements the above properties in the stated
order. Its calling syntax is Diff(expression, identifier).
                                                                                 17-39
17   MuPAD® Procedures
                         function map:
                          map(f1(x) + f2(x) + f3(x), Diff, x)
                              Diff(f1(x) , x) + Diff(f2(x) , x) + Diff(f3(x) , x)
                          Diff(f(x)*sin(x^2), x)
                                 ( )                          ( )
                              sin x2 Diff(f (x) , x) + 2 x cos x2 f (x)
     17-40
                                                                                Programming Exercises
Programming Exercises
             Exercise 17.3: Write a short procedure date that takes three integers month, day,
             year as input and prints the date in the usual way. For example, the call
             date(5, 3, 1990) should yield the screen output 5/3/1990.
             The “(3 x + 1) problem” asks whether for an arbitrary initial value x0 ∈ N, the
             sequence recursively defined by xi+1 := f (xi ) contains the value 1. Write a
             program that on input x0 returns the smallest index i with xi = 1.
                                                                                                 17-41
17   MuPAD® Procedures
                          formula := (x and y) or
                                     ((y or z) and (not x) and y and z)
                         Such a formula is called satisfiable if it is possible to assign the values TRUE and
                         FALSE to all identifiers in such a way that the formula can be evaluated to TRUE.
                         Write a program that checks whether an arbitrary logical formula is satisfiable.
     17-42
                                                                    A
Solutions to Exercises
       Exercise 2.1: The help page ?diff tells you how to compute higher order
       derivatives:
        diff(sin(x^2), x, x, x, x, x)
                     ( )            ( )             ( )
            32 x5 cos x2 − 120 x cos x2 + 160 x3 sin x2
You can also use the longer command diff(diff(..., x), x).
       Exercise 2.3:
        expand((x^2 + y)^5)
            x10 + 5 x8 y + 10 x6 y 2 + 10 x4 y 3 + 5 x2 y 4 + y 5
A   Solutions to Exercises
                             Exercise 2.4:
                              normal((x^2 - 1)/(x + 1))
                                 x−1
                             Exercise 2.5: You can plot the singular function f (x) = 1/ sin(x) on the interval
                             [1, 10] without any problems:
                              plot(1/sin(x), x = 1..10)
    A-2
                                                                    Solutions to Exercises
 limit(x^ln(x), x = 0, Right),
 limit((1 + PI/x)^x, x = infinity),
 limit(2/(1 + exp(-1/x)), x = 0, Left)
    ∞, eπ , 0
Exercise 2.7: You obtain the first result in the desired form by factoring:
 sum(k^2 + k + 1 , k = 1..n): % = factor(%)
                      ( )
     n3        5n      1       (             )
        + n2 +    =       · n · n2 + 3 n + 5
     3          3      3
Exercise 2.8:
 A := matrix([[1, 2, 3], [4, 5, 6], [7, 8, 0]]):
 B := matrix([[1, 1, 0], [0, 0, 1], [0, 1, 0]]):
 2*(A + B), A*B
                             
      4       6 6        1 4 2
                             
     8      10 14  ,  4 10 5 
          14 18   0       7   7   8
                                                                                      A-3
A   Solutions to Exercises
                              (A - B)^(-1)
                                                         
                                     − 52    3
                                             2     − 57
                                                         
                                     5
                                      2     − 32    6
                                                    7
                                                          
                                     − 12    1
                                             2     − 27
2305843009213693951, 618970019642690137449562111,
162259276829213363391578010288127, ... ]
                             b) Depending on your computer’s speed, you can test only the first 13 or 14 Fermat
                             numbers in a reasonable amount of time. Note that the 12-th Fermat number
                             already has 1234 decimal digits.
                              Fermat := n -> 2^(2^n) + 1: isprime(Fermat(10))
                                 FALSE
                             The only known Fermat primes are the first five Fermat numbers (including
                             Fermat(0)). Indeed, if MuPAD tests the first 12 Fermat numbers, then after some
                             time it returns the following five values:
    A-4
                                                                     Solutions to Exercises
Exercise 4.1: The first operand of a power is the base, the second is the
exponent. The first and second operand of an equation is the left and the
right-hand side, respectively. The operands of a function call are its arguments:
 op(a^b, 1), op(a^b, 2)
    a, b
 op(a = b, 1), op(a = b, 2)
    a, b
 op(f(a, b), 1), op(f(a, b), 2)
    a, b
Exercise 4.2: The list with the two equations is op(set, 1). Its second operand
is the equation y = ..., whose second operand is the right-hand side:
 set := solve({x+sin(3)*y = exp(a),
               y-sin(3)*y = exp(-a)}, {x,y})
    {[                         sin(3)
                                                               ]}
            ea sin(3) − ea +                        1
         x=                      ea
                                        ,y = − a
                  sin(3) − 1                  e (sin(3) − 1)
                                                                                       A-5
A   Solutions to Exercises
                             Note that only the first 10 digits of these values are reliable since this is the default
                             precision. Indeed, for larger values of DIGITS, you find:
                              DIGITS := 100:
                              float(PI^(PI^PI)), float(exp(PI*sqrt(163)/3))
                                1340164183006357435.297449129640131415099374974573499\
                                237787927516586034092619094068148269472611301142
                                640320.0000000006048637350490160394717418188185394757\
                                714857603665918194652218258286942536340815822646
                             We compute 235 decimal digits of PI to obtain the correct 234-th digit after the
                             decimal point. After setting DIGITS:= 235, the result is the last shown digit of
                             float(PI). A more elegant way is to multiply by 10234 . Then the desired digit is
                             the first digit before the decimal point, and we obtain it by truncating the digits
                             after the decimal point:
                              DIGITS := 235: trunc(10^234*PI) - 10*trunc(10^233*PI)
                                  6
                             Exercise 4.5: a) Internally, MuPAD computes with some additional digits not
                             shown in the output.
                              DIGITS := 10: x := 10^50/3.0; floor(x)
                                  3.333333333 · 1049
33333333333333333307484730568084080731669827420160
    A-6
                                                                     Solutions to Exercises
b) After increasing DIGITS, MuPAD displays the additional digits. However, not
all of them are correct:
 DIGITS := 40: x
    3.333333333333333330748473056808408073167 · 1049
Restart the computation with the increased value of DIGITS to obtain the desired
precision:
 DIGITS := 40: x := 10^50/3.0
    3.333333333333333333333333333333333333333 · 1049
Exercise 4.6: The names caution!-!, x-y, and Jack&Jill are invalid since they
contain the special characters !, -, and &, respectively. Since an identifier’s name
must not start with a number, 2x is not valid either. The names diff and exp are
valid names of identifiers. However, you cannot assign values to them since they
are protected names of MuPAD functions. The name #1 is a valid name of
identifier. However, you cannot assign values to it because, starting with a hash
mark, it cannot be assigned to.
Exercise 4.7: We use the sequence operator $ (page 4-24) to generate the set of
equations and the set of unknowns. Then a call to solve returns a set of simpler
equations:
 equations := {(x.i + x.(i+1) = 1) $ i = 1..19,
                x20 = PI}:
 unknowns := {x.i $ i = 1..20}:
 solutions := solve(equations, unknowns)
   {[x1 = 1 - PI, x10 = PI, x11 = 1 - PI, x12 = PI,
                                                                                       A-7
A   Solutions to Exercises
                             We use the function assign to assign the computed values to the identifiers:
                              assign(op(solutions, 1)): x1, x2, x3, x4, x5, x6
                                 1 − π, π, 1 − π, π, 1 − π, π
                             Exercise 4.8: MuPAD stores the expression a^b - sin(a/b) in the form
                             sin(a * b^(-1)) * (-1) + a^b. Its expression tree is:
* ^
                                                                          a       b
                                                 sin               -1
a ^
b -1
                             The reason is that 2/3 is of domain type DOM_RAT, whose operands are the
                             numerator and the denominator. The domain type of the symbolic expression x/3
                             is DOM_EXPR and its internal representation is x * (1/3). The situation is similar for
                             1 + 2 * I and x + 2 * I:
                              op(1 + 2*I); op(x + 2*I)
                                 1, 2
x, 2 i
    A-8
                                                                     Solutions to Exercises
The first object is of domain type DOM_COMPLEX. Its operands are the real and the
imaginary part. The operands of the symbolic expression x + 2 * I are the first and
the second term of the sum.
not or
a b c
Exercise 4.11: You can use both the assignment function _assign presented on
page 4-8 and the assignment operator :=.
 for i from 1 to 100 do _assign(x.i, i); end:
 for i from 1 to 100 do x.i := i; end:
You can also pass a set of assignment equations to the assign function:
 assign({x.i = i $ i = 1..100}):
                                                                                       A-9
A   Solutions to Exercises
                             Exercise 4.13: We use the addition function _plus and generate its argument
                             sequence via $:
                              _plus(((i+j)^(-1) $ j = 1.. i) $ i=1..10)
                                 1464232069
                                 232792560
                             Exercise 4.14:
                              L1 := [a, b, c, d]: L2 := [1, 2, 3, 4]:
                              L1.L2, zip(L1, L2, _mult)
                                 [a, b, c, d, 1, 2, 3, 4] , [a, 2 b, 3 c, 4 d]
                             We use map to apply the function sublist -> map(sublist, _mult, 2) to the
                             sublists in a nested list:
                              L := [[1, x, 2], [PI], [2/3, 1]]:
                              map(L, map, _mult, 2)
                                 [                           [       ]]
                                                                 4
                                     [2, 2 x, 4] , [2 π] ,         ,2
                                                                 3
    A-10
                                                                               Solutions to Exercises
The following function f multiplies each element of the list Y by its input
parameter x and returns the resulting list:
 f := x -> (map(Y, _mult, x)):
Exercise 4.17: For each m, we use the sequence generator $ to create a list of all
integers to be checked. Then we extract all primes from the list via
select(·, isprime). The number of primes is just nops of the resulting list. We
compute this value for all m between 0 and 41:
 nops(select([(n^2 + n + m) $ n = 1..100], isprime))
   $ m = 0..41
    1, 32, 0, 14, 0, 29, 0, 31, 0, 13, 0, 48, 0, 18, 0,
There is a simple explanation for the zero values for even m > 0. Since
n2 + n = n (n + 1) is always even, n2 + n + m is an even integer greater than 2 and
hence not a prime.
Exercise 4.18: We store the children in a list C and remove the one that was
counted out at the end of each round. We represent the positions 1, 2, . . . , n of n
children by a list with the corresponding integers. Let out ∈ {1, . . . , n} be the
position of the last child that was counted out. After deleting the out-th element,
the next round begins at position out in the shortened list. At the end of the
round, after m words, the child at position out + m - 1 in the current list is counted
out. Since we are counting cyclically, we take this value modulo the number of
remaining children. Note, however, that a mod b produces numbers in the range
0, 1, . . . , b − 1 rather than 1, . . . , b. This is overcome by using ((a - 1) mod b) + 1
instead of a mod b:
 m := 8: n := 12: C := [$ 1..n]: out := 1:
                                                                                                A-11
A   Solutions to Exercises
11
...
                             Exercise 4.19:
                              set := {op(list)}:      list := [op(set)]:
                             Note that the two conversions list 7→ set 7→ list in general change the order of the
                             list elements.
    A-12
                                                                      Solutions to Exercises
Exercise 4.20:
 A := {a, b, c}: B := {b, c, d}: C := {b, c, e}:
 A union B union C, A intersect B intersect C,
 A minus (B union C)
    {a, b, c, d, e} , {b, c} , {a}
Exercise 4.22:
 telephoneDirectory := table(Ford = 1815,
   Reagan = 4711, Bush = 1234, Clinton = 5678):
You can use select to extract all table entries containing the number 5678:
 select(telephoneDirectory, has, 5678)
Clinton 5678
                                                                                      A-13
A   Solutions to Exercises
                             Exercise 4.24: The following timings (in milliseconds) show that generating a
                             table is more time consuming:
                              n := 100000:
                              time((T := table((i=i) $ i=1..n))),
                              time((L := [i $ i=1..n]))
                                 422, 165
                             However, working with tables is notably faster. The following assignments create
                             an additional table entry and extend the list by one element, respectively:
                              time((T[n + 1] := New)), time((L := L.[New]))
                                 0, 84
                             Exercise 4.25: We use the sequence generator $ to create a nested list and pass
                             it to array:
                              n := 20:
                              array(1..n, 1..n,
                                [[1/(i + j - 1) $ j = 1..n] $ i = 1..n]):
                             Exercise 4.26:
                              TRUE and (FALSE or not (FALSE or not FALSE))
                                 FALSE
    A-14
                                                                      Solutions to Exercises
125 < 190 and 144 < 294 and 147 < 434 and
Exercise 4.28: The function sort does not sort the identifiers alphabetically by
their names but according to an internal order (page 4-28). Thus, we convert
them to strings via expr2text before sorting:
 sort(map(anames(All), expr2text))
   ["Ax", "Axiom", "AxiomConstructor", "C_", "Cat",
Exercise 4.30:
 f := x -> (x^2): g := x -> (sqrt(x)):
                                                                                      A-15
A   Solutions to Exercises
                              (f@f@g)(2), (f@@100)(x)
                                 4, x1267650600228229401496703205376
                             Exercise 4.32: You can use the function last (Chapter 13.2) to generate the
                             Chebyshev polynomials as expressions:
                              T0 := 1: T1 := x:
                              T2 := 2*x*% - %2; T3:= 2*x*% - %2; T4:= 2*x*% - %2
                                 2 x2 − 1
                                     (        )
                                 2 x 2 x2 − 1 − x
                                                (      (         ))
                                 1 − 2 x2 − 2 x x − 2 x 2 x2 − 1
                             A much more elegant way is to translate the recursive definition into a MuPAD
                             function that works recursively:
                              T := (k, x) ->
                                   (if k < 2
                                       then x^k
                                       else 2*x*T(k - 1, x) - T(k - 2, x)
                                    end_if):
                             Then we obtain:
                              T(i, 1/3) $ i = 2..5
                                  7   23 17 241
                                 − , − ,   ,
                                  9   27 81 243
    A-16
                                                                              Solutions to Exercises
                     2                             2
         1 - 2 x             - 2 x (x - 2 x (2 x       - 1)), x -
                         2                                      2
         2 x (2 x            - 1) - 2 x (2 x (x - 2 x (2 x          - 1)) +
               2
         2 x       - 1)
The Chebyshev polynomials are already implemented in orthpoly, the library for
orthogonal polynomials. The i-th Chebyshev polynomial is returned by the call
orthpoly::chebyshev1(i, x).
Exercise 4.33: In principle, you can compute the derivatives of f in MuPAD and
substitute x = 0. But it is simpler to approximate the function by a Taylor series
whose leading terms describe the behavior in the neighborhood of x = 0:
 taylor(tan(sin(x)) - sin(tan(x)), x = 0)
     x7   29 x9   1913 x11    ( )
        +       +          + O x13
     30    756     75600
Thus, f (x) = x7 /30 · (1 + O(x2 )), and hence f has a root of order 7 at x = 0.
                                                                                               A-17
A   Solutions to Exercises
                             Exercise 4.34: The reason for the difference between the results
                              taylor(diff(1/(1 - x), x), x);
                              diff(taylor(1/(1 - x), x), x)
                                                                        ( )
                                 1 + 2 x + 3 x2 + 4 x3 + 5 x4 + 6 x5 + O x6
                                                                  ( )
                                 1 + 2 x + 3 x2 + 4 x3 + 5 x4 + O x5
                             is the truncation determined by the environment variable ORDER with the default
                             value 6. Both taylor calls compute the corresponding series up to O(x6 ):
                              taylor(1/(1 - x), x)
                                                              ( )
                                 1 + x + x2 + x3 + x4 + x5 + O x6
                             The order term O(x^5) appears when the term O(x^6) is differentiated:
                              diff(%, x)
                                                                 ( )
                                 1 + 2 x + 3 x2 + 4 x3 + 5 x4 + O x5
                             Thus                           (                               )
                                                        1             1       7
                                                   f≈√         1 +       +         +  · · ·   ,
                                                         x          8 x2    128 x4
                                                   √
                                         (x) ≈ 1/ )
                             and hence f (          x for all real x ≫ 1. The next better approximation is
                                      1          1
                             f (x) ≈ √     1+        .
                                       x       8 x2
    A-18
                                                                     Solutions to Exercises
Exercise 4.36: The command ?revert requests the corresponding help page.
 f := taylor(sin(x + x^3), x); g := revert(%)
         5 x3   59 x5    ( )
    x+        −       + O x7
           6     120
         5 x3   103 x5    ( )
    x−        +        + O x7
           6      40
Exercise 4.37: We perform the computation over the standard coefficient ring
(page 4-64), which comprises both rational numbers and floating-point numbers:
 n := 16:
 H := matrix(n, n, (i, j) -> ((i + j -1)^(-1))):
 e := matrix(n, 1, 1): b := H*e:
                                                                                     A-19
A   Solutions to Exercises
                             Exercise 4.38: We look for values where the determinant of the matrix vanishes:
                              matrix([[1, a, b], [1, 1, c], [1, 1, 1]]):
                              factor(linalg::det(%))
                                 (c − 1) · (a − 1)
                             Exercise 4.39: We first store the matrix data in arrays. These arrays are used
                             later to generate matrices over different coefficient rings:
                              a := array(1..3, 1..3, [[ 1, 3, 0],
                                                      [-1, 2, 7],
                                                      [ 0, 8, 1]]):
                              b := array(1..3, 1..2, [[7, -1], [2, 3], [0, 1]]):
                             Now we define the constructor MQ for matrices over the rational numbers and
                             convert the arrays to corresponding matrices:
                              MQ := Dom::Matrix(Dom::Rational): A := MQ(a): B := MQ(b):
    A-20
                                                                    Solutions to Exercises
We check this by multiplying the inverse by the original matrix, which yields the
identity matrix over the coefficient ring:
 %*C
                             
      1 mod 7 0 mod 7 0 mod 7
                             
     0 mod 7 1 mod 7 0 mod 7 
      0 mod 7 0 mod 7 1 mod 7
                                                                                    A-21
A   Solutions to Exercises
                             The determinant of A is
                              linalg::det(A)
                                  2
                             Let Id denote the 3 × 3 identity matrix. The eigenspace for the eigenvalue
                             λ ∈ {−1, 2} is the solution space of the system of linear equations
                             (A − λ · Id) ⃗x = ⃗0. The solution vectors span the nullspace (the “kernel”) of the
                             matrix A − λ · Id. The function linalg::nullspace computes a basis for the
                             kernel of a matrix:
                              Id := MQ::identity(3):
                              lambda := -1: linalg::nullspace(A - lambda*Id)
                                                   
                                       −1         −1
                                           
                                   1  ,  0 
                                     0       1
                             There are two linearly independent basis vectors. Hence the eigenspace for the
                             eigenvalue λ = −1 is two-dimensional. The other eigenvalue is simple:
    A-22
                                                                        Solutions to Exercises
The return value is a nested list. For each eigenvalue λ, it contains a list of the form
Exercise 4.41:
 p := poly(x^7 - x^4 + x^3 - 1): q := poly(x^3 - 1):
 p - q^2
         (                            )
     poly x7 − x6 − x4 + 3 x3 − 2, [x]
 factor(q)
                             (                )
     poly (x − 1, [x]) · poly x2 + x + 1, [x]
                                                                                           A-23
A   Solutions to Exercises
                             Exercise 4.42: We use the identifier R to abbreviate the lengthy type name
                             Dom::IntegerMod(3). With alias, MuPAD also uses R as an alias in the output of
                             the following polynomials.
                              p := 3: alias(R = Dom::IntegerMod(p)):
                             We only need to try the possible remainders 0, 1, 2 modulo 3 for the coefficients
                             a, b, c in a x2 + b x + c. We generate a list of all 18 quadratic polynomials with a ̸= 0
                             as follows:
                              [((poly(a*x^2 + b*x + c, [x], R) $ a = 1..p-1)
                                 $ b = 0..p-1) $ c = 0..p-1]:
                                                  2
                                    poly(2 x          + 2 x + 1, [x], R),
                                                  2                          2
                                    poly(2 x          + 2, [x], R), poly(x       + x + 2, [x], R),
                                              2
                                    poly(x        + 2 x + 2, [x], R)]
                             Exercise 5.1: The value of x is the identifier a1. The evaluation of x yields the
                             identifier c1. The value of y is the identifier b2. The evaluation of y yields the
                             identifier c2. The value of z is the identifier a3. The evaluation of z yields 10.
                             The evaluation of u1 leads to an infinite recursion, which MuPAD aborts with an
                             error message. The evaluation of u2 yields the expression v2^2 - 1.
    A-24
                                                                     Solutions to Exercises
       f0 f6   25 f2 f4   10 f0 f2 f5   20 f0 f3 f4
       ----- + -------- + ----------- + ----------- -
           2         2           3             3
        f1        f1          f1            f1
                   2            3               2
       90 f0 f2 f3    240 f0 f2 f3    60 f0 f2 f4
       ------------ + ------------- - ------------
               4              5               4
            f1             f1              f1
Exercise 7.1: The following commands yield the desired evaluation of the
function:
 f := sin(x)/x: x := 1.23: f
    0.7662510585
However, x now has a value. The following call diff(f, x) would internally lead
to the command diff(0.7662510584, 1.23), since diff evaluates its arguments.
                                                                                     A-25
A   Solutions to Exercises
                             Here the evaluation of hold(x) is the identifier x and not its value. Writing
                             hold(f) instead of level(f, 1) would yield the wrong result
                             diff(hold(f),hold(x)) = 0, since hold(f) does not contain hold(x). Using
                             level(f, 1) replaces f by its value sin(x)/x (page 5-4). The next call of g returns
                             the evaluation of g, namely the value of the derivative at x = 1.23. Alternatively
                             you can delete the value of x:
                              delete x: diff(f, x) | x = 1.23
                                  −0.3512303507
                             Exercise 7.2: The first three derivatives of the numerator and the denominator
                             vanish at the point x = 0:
                              Z := x -> (x^3*sin(x)): N := x -> ((1 - cos(x))^2):
                              Z(0), N(0), Z'(0), N'(0), Z''(0), N''(0),
                              Z'''(0), N'''(0)
                                  0, 0, 0, 0, 0, 0, 0, 0
                             Thus the limit is Z ′′′′ (0)/N ′′′′ (0) = 4, according to de l’Hospital’s rule. The
                             function limit computes the same result:
                              limit(Z(x)/N(x), x = 0)
                                  4
    A-26
                                                                    Solutions to Exercises
                                                   2
         cos(x1 x2) - x1 x2 sin(x1 x2), - x1           sin(x1 x2)
Exercise 7.4:
 int(sin(x)*cos(x), x = 0..PI/2),
 int(1/(sqrt(1 - x^2)), x = 0..1),
 int(x*arctan(x), x = 0..1),
 int(1/x, x = -2..-1)
     1 π π 1
      , ,  − , − ln(2)
     2 2 4  2
Exercise 7.5:
 int(x/(2*a*x - x^2)^(3/2), x)
                x
         √
     a       2 a x − x2
 int(sqrt(x^2 - a^2), x)
      √                (   √        )
     x x 2 − a2   a2 ln x + x2 − a2
                −
         2                 2
                                                                                    A-27
A   Solutions to Exercises
                              int(1/(x*sqrt(1 + x^2)), x)
                                               (√           )
                                 ln(x) − ln      x2 + 1 + 1
                             The free parameters are on the right-hand sides of the solved equations. You can
                             determine them in MuPAD by extracting the right hand sides and using indets to
                             find the identifiers contained therein:
    A-28
                                                                       Solutions to Exercises
{z, z1}
with free constants C1, C2. We remove the outer curly braces via op:
 solution := op(solution)
    [                                                ]
                 C2 e2 x  C1         C1
        z(x) =           − x , y(x) = x + C2 e2 x
                   2      e          e
Now, we set x = 0 and substitute y(0) and z(0), respectively, for the initial
conditions. Then, we solve the resulting linear system of equations for C1 and C2:
 solve((solution | x = 0) | [y(0) = 1, z(0) = 1],
       {C1, C2})
    {[                ]}
            1       4
      C1 = − , C2 =
            3       3
Again, we remove the outer curly braces via op and assign the solution values to C1
and C2 by means of assign:
 assign(op(%)):
Thus, the value at x = 1 of the symbolic solution for the above initial conditions is:
 x := 1: solution
    [                                            ]
               1    2 e2          4 e2   1
        z(1) =    +      , y(1) =      −
               3e    3             3     3e
                                                                                         A-29
A   Solutions to Exercises
                             Exercise 8.3:
                              solve(ode(y'(x)/y(x)^2 = 1/x, y(x)))
                                 {                    }
                                           1
                                  −
                                       C3 + ln(x)
    A-30
                                                                   Solutions to Exercises
 solve(ode({diff(x(t),t) = y(t)*z(t),
            diff(y(t),t) = x(t)*z(t),
            diff(z(t),t) = t*z(t)},
           {x(t),y(t),z(t)}))
   {   --
   {   |
   {   | x(t) =
   {   --
y(t) =
                     / 2     \ -- }
                     | t     | | }
       z(t) = C10 exp| --    | | }
                     \ 2     / -- }
Exercise 8.4: The function solve directly yields the solution of the recurrence:
                                                                                   A-31
A   Solutions to Exercises
                             Exercise 9.1:
                             You get the answer by applying combine to rewrite products of trigonometric
                             functions as sums:
                              combine(cos(x)^2 + sin(x)*cos(x), sincos)
                                 cos(2 x) sin(2 x) 1
                                         +        +
                                    2        2      2
                             Exercise 9.2:
                              expand(cos(5*x)/(sin(2*x)*cos(x)^2))
                                         2                      3
                                 cos(x)                5 sin(x)
                                          − 5 sin(x) +          2
                                 2 sin(x)              2 cos(x)
                              f := (sin(x)^2 - exp(2*x)) /
                                   (sin(x)^2 + 2*sin(x)*exp(x) + exp(2*x)):
                              normal(expand(f))
                                     ex − sin(x)
                                 −
                                     ex + sin(x)
                              f := (sin(2*x) - 5*sin(x)*cos(x)) /
                                   (sin(x)*(1 + tan(x)^2)):
                              combine(normal(expand(f)), sincos)
                                      3 cos(x)
                                 −           2
                                     tan(x) + 1
                              f := sqrt(14 + 3*sqrt(3 +
                                                2*sqrt(5 - 12*sqrt(3 - 2*sqrt(2))))):
    A-32
                                                                    Solutions to Exercises
 simplify(f, sqrt)
    √
     2+3
                                                                                    A-33
A   Solutions to Exercises
                             Exercise 9.4: The problem obviously is that the valuation function does not look
                             carefully enough at the term to analyze. To remedy this, we use the function
                             length which returns a general, quickly computed “complexity:”
                             Exercise 10.1: In analogy to the previous gcd example, we obtain the following
                             experiment:
                              die := random(1..6):
                              experiment := [[die(), die(), die()] $ i = 1..216]:
                              diceScores := map(experiment,
                                                x -> (x[1] + x[2] + x[3])):
                              frequencies := Dom::Multiset(op(diceScores)):
                              sortingOrder := (x, y) -> (x[1] < y[1]):
    A-34
                                                                    Solutions to Exercises
 sort([op(frequencies)], sortingOrder)
   [[4, 4], [5, 9], [6, 8], [7, 9], [8, 16], [9, 20],
[10, 27], [11, 31], [12, 32], [13, 20], [14, 13],
returns a list with the absolute values of n random vectors in the rectangle
Q = [0, 1] × [0, 1]. The number of values ≤ 1 is the number of random points in the
right upper quadrant of the unit circle:
 m := nops(select(absValues, z -> (z <= 1)))
    821
Since m/n approximates the area π/4 of the right upper quadrant of the unit circle,
we obtain the following approximation to π :
 float(4*m/n)
    3.284
b) First we determine the maximum of f . The following function plot shows that f
is monotonically increasing on the interval [0, 1]:
                                                                                      A-35
A   Solutions to Exercises
                             Thus f (x) assumes its maximal value at the right end of the interval. Therefore,
                             M = f (1) is an upper bound for the function:
                              M := f(1.0)
                                 2.310164925
                             We use the random number generator defined above to generate random points in
                             the rectangle [0, 1] × [0, M ]:
                              n := 1000:
                              pointlist := [[frandom(), M*frandom()] $ i = 1..n]:
    A-36
                                                                       Solutions to Exercises
Exercise 13.1: With the following definition of the postOutput method of Pref,
the system prints an additional status line:
 Pref::postOutput(
   proc()
   begin
     "bytes: " .
     expr2text(op(bytes(), 1)) . " (logical) / " .
     expr2text(op(bytes(), 2)) . " (physical)"
    end_proc):
 float(sum(1/i!, i = 0..100))
    2.718281828
Then we apply domtype to all elements of the set to determine their domain types:
 map(S, domtype)
    {DOM_RAT, DOM_INT, DOM_EXPR}
You see the explanation for this result by looking at some elements:
 f(-2), f(0), f(1), f(2), f(3), f(4)
               5         √             √        √
          (−2) 2 + 3 −    2i          3 2+3 8 3+8 3
            3        5      √ , −1, 0, √     ,  √      ,
     2 (−2) 2 + (−2) 2 + 1 + 2 i      9 2 + 9 16 3 + 16 5
                                                                                       A-37
A   Solutions to Exercises
                              map(%, normal)
                                             1 1 3
                                 3, −1, 0,    , ,
                                             3 2 5
                             Now we apply normal to all elements of the set before querying their data type:
                              map(S, domtype@normal)
                                 {DOM_RAT, DOM_INT}
                             Thus, all numbers in S are indeed rational (in particular there are two integer
                             values f(0) = -1 and f(1) = 0). The reason is that f(i) can be simplified to
                             (i - 1)/(i + 1):
                              normal(f(i))
                                  i−1
                                  i+1
                             to find out whether it is returned in the form sin(·). The following split
                             command (page 4-36) decomposes the list accordingly:
                              decomposition := split(list, testtype, "sin"):
    A-38
                                                                      Solutions to Exercises
Exercise 14.3: You can use select (page 4-36) to extract those elements that
testtype identifies as positive integers. For example:
Note that this selects only those objects that are positive integers, but not those
that might represent positive integers, such as the identifier x in the above
example. This is not possible with testtype. Instead, you can use assume to set
this property and query it via is:
 assume(x, Type::PosInt):
 select(set, is, Type::PosInt)
    {2, 4, x}
                                                                                      A-39
A   Solutions to Exercises
                             Exercise 14.4: We construct the desired type specifier and employ it as follows:
                              T := Type::ListOf(Type::ListOf(
                                     Type::AnyType, 3, 3), 2, 2)
                                  Type::ListOf(Type::ListOf(Type::AnyType, 3, 3) , 2, 2)
    A-40
                                                                      Solutions to Exercises
Exercise 17.1: With the formulas given, implementation of the "float" slots is
straightforward:
 ellipE::float := z -> float(PI/2) *
   hypergeom::float([-1/2, 1/2], [1], z):
 ellipK::float := z -> float(PI/2) *
   hypergeom::float([1/2, 1/2], [1], z):
 float(%)
     1.430315257
However, one thing is missing: we would like to have calls with floating point
arguments evaluated immediately:
 ellipE(0.1)
     E(0.1)
Extend ellipK analogously, then make these new functions into function
environments (the above definition replaced the old one completely) and add the
function slots we used for the original definitions and the new float slots, and you
get:
                                                                                       A-41
A   Solutions to Exercises
                              ellipE(0.1)
                                 1.530757637
                             The diff attribute of the system function abs yields a slightly different but
                             equivalent result:
                              diff(Abs(x^3), x), diff(abs(x^3), x)
                                   3 |x^3|       2
                                   -------, 3 |x| sign(x)
                                      x
    A-42
                                                                 Solutions to Exercises
Exercise 17.3: We use expr2text (page 4-49) to convert the integers passed as
arguments to strings. Then we combine them, together with some slashes, via the
concatenation operator “.”:
 date := proc(month, day, year) begin
             print(Unquoted, expr2text(month) . "/" .
                             expr2text(day) . "/" .
                             expr2text(year))
         end_proc:
Exercise 17.4: We present a solution using a while loop. The condition x mod
2 = 0 checks whether x is even:
 f := proc(x) local i;
 begin
   i := 0;
   userinfo(2, "term " . expr2text(i) . ": " .
               expr2text(x));
   while x <> 1 do
     if x mod 2 = 0 then x := x/2
     else x := 3*x+1 end_if;
     i := i + 1;
     userinfo(2, "term " . expr2text(i) . ": " .
                 expr2text(x))
   end_while;
   i
 end_proc:
 f(4), f(1234), f(56789), f(123456789)
    2, 132, 60, 177
If we set setuserinfo(f, 2) (page 13-9), then the userinfo command outputs all
terms of the sequence until the procedure terminates:
 setuserinfo(f, 2): f(4)
  Info: term 0: 4
  Info: term 1: 2
  Info: term 2: 1
                                                                                  A-43
A   Solutions to Exercises
                             in the next step. Thus the function gcd would always call itself recursively with the
                             same arguments. However, a recursive call of the form gcd(a, b) = gcd(b, a mod b)
                             make sense. Since a mod b < b, the function calls itself recursively for decreasing
                             values of the second argument, which finally becomes zero:
                              Gcd := proc(a, b) begin     /* recursive variant */
                                         if b = 0
                                            then a
                                            else Gcd(b, a mod b)
                                         end_if
                                     end_proc:
                             For large values of a and b, you may need to increase the value of the environment
                             variable MAXDEPTH if Gcd exhausts the valid recursion depth. The following
                             iterative variant avoids this problem:
                              GCD := proc(a, b)
                                     begin
                                       while b <> 0 do
                                         [a, b] := [b, a mod b];
                                       end_while;
                                       a
                                     end_proc:
                             These implementations yield the same results as the functions igcd and gcd
                             provided by the system:
                              a := 123456: b := 102880:
                              Gcd(a, b), GCD(a, b), igcd(a, b), gcd(a, b)
                                 20576, 20576, 20576, 20576
    A-44
                                                                       Solutions to Exercises
 Quadrature := proc(f, X)
 local Y, distances, numericalValues, products;
 begin
    Y := X; delete Y[1];
    distances := zip(Y, X, _subtract);
    numericalValues := map(X, float@f);
    products := zip(distances, numericalValues, _mult);
    _plus(op(products))
 end_proc:
                                                                                         A-45
A   Solutions to Exercises
                             Exercise 17.7: The specification of Newton requires that the first argument f be
                             an expression and not a MuPAD function. Thus, to compute the derivative, we
                             first use indets to determine the unknown in f. We substitute a numerical value
                             for the unknown to evaluate the iteration function F (x) = x − f (x)/f ′ (x) at a
                             point:
                              Newton := proc(f, x0, n)
                                local vars, x, F, sequence, i;
                                begin
                                  vars := indets(float(f)):
                                  if nops(vars) <> 1
                                      then error(
                                   "the function must contain exactly one unknown"
                                                )
                                      else x := op(vars)
                                  end_if;
                                  F := x - f/diff(f,x); sequence := x0;
                                  for i from 1 to n do
                                       x0 := float(subs(F, x = x0));
                                       sequence := sequence, x0
                                  end_for;
                                  return(sequence)
                                end_proc:
1.414213562, 1.414213562
    A-46
                                                                 Solutions to Exercises
                                                                                 A-47
A   Solutions to Exercises
plotNewton(sin(x)+5*sin(x/3), 4, 3)
    A-48
                                                                    Solutions to Exercises
We use select (page 4-28) to extract the Sierpinski points from all points
considered. Finally, we create a plot::PointList2d with these points and call
plot (page 11-1):
For xmax = ymax = 100, say, you obtain a quite appealing picture:
 Sierpinski(100, 100)
                                                                                    A-49
A   Solutions to Exercises
                             If the number of identifiers in the input formula is n, then the recursion depth is
                             at most n and the total number of recursive calls of the procedure is at most 2n .
                             We apply this procedure in two examples:
                              F1 := ((x and y) or (y or z)) and (not x) and y and z:
                              F2 := ((x and y) or (y or z)) and (not y) and (not z):
                              satisfiable(F1), satisfiable(not F1),
                              satisfiable(F2), satisfiable(not F2)
                                 TRUE, TRUE, FALSE, TRUE
                             The call simplify(·, logic) (page 9-13) simplifies logical formulae. Formula F2
                             can be simplified to false, no matter what the values of x, y , and z are:
                              simplify(F1, logic), simplify(F2, logic)
¬x ∧ y ∧ z, FALSE
    A-50
                                                                       B
      You can find a list of all documents that are available in your installation by
      choosing “Browse Help” from the “Help” menu of any MuPAD® notebook window
      and then clicking on “Contents”.
      The MuPAD Quick Reference lists all MuPAD data types, functions, and libraries,
      and provides a survey of its functionality.
      You also find links to various libraries such as, for example, Dom (the library for
      pre-installed data types). The corresponding documentation contains a concise
      description of all domains provided by Dom. In a MuPAD session, the command
      ?Dom directly opens this document. Moreover, you can access the description of
      individual data structures from this document, such as Dom::Matrix, directly
      through the call ?Dom::Matrix. Another example is the documentation for the
      linalg package (linear algebra). It can be requested directly via ?linalg.
      [Maj 05] M. Majewski Getting Started with MuPAD. Springer Heidelberg, 2005.
               ISBN 3-540-28635-7
      [Wes 99] M. Wester (ed.), Computer Algebra Systems. A Practical Guide. Wiley,
               1999.
B   Documentation and References
                       [GG 99]     J. von zur Gathen and J. Gerhard, Modern Computer Algebra.
                                   Cambridge University Press, 1999.
                       [DTS 93] J.H. Davenport, E. Tournier and Y. Siret, Computer Algebra: Systems
                                and Algorithms for Algebraic Computation. Academic Press, 1993.
                       [GCL 92] K.O. Geddes, S.R. Czapor and G. Labahn, Algorithms for Computer
                                Algebra. Kluwer, 1992.
    B-2
C
C   Graphics Gallery
Graphics Gallery
    C-2
Graphics Gallery
            C-3
C   Graphics Gallery
    C-4
Graphics Gallery
            C-5
C   Graphics Gallery
    C-6
Graphics Gallery
            C-7
C   Graphics Gallery
    C-8
Graphics Gallery
            C-9
C   Graphics Gallery
    C-10
Graphics Gallery
           C-11
C   Graphics Gallery
    C-12
Graphics Gallery
           C-13
C   Graphics Gallery
    C-14
Graphics Gallery
           C-15
C   Graphics Gallery
    C-16
Graphics Gallery
           C-17
                                                                          D
      On the color pages of this book you find a gallery of pictures demonstrating the
      power of the MuPAD® graphics. These pictures are discussed at various locations
      in this book and the online plot documentation, respectively. There, further
      details including the MuPAD commands for reproducing the pictures can be
      found.
      Figure 1 shows a plot of several functions. Singularities are highlighted by
      “vertical asymptotes.” See page 11-3. Figure 2 shows a function plot together
      with a spline interpolation through a set of sample points. See page 11-39.
      Figure 3 demonstrates some layout possibilities. See the examples on the help
      page of the graphical attribute Layout in the online plot documentation.
      Figure 4 demonstrates the construction of cycloids via points fixed to a rolling
      wheel. See page 11-41.
      Figure 5 and Figure 6 demonstrate hatched areas between functions and within
      closed curves, respectively. See the examples on the help page of plot::Hatch.
      Figure 7 shows various statistical distribution functions.
      Figure 8 shows an imported bitmap inside function plots. See page 11-110.
      Figure 9 shows some frames of an animation of the perturbed orbit of a small
      planet kicked out of a solar system by a giant planet after a near-collision. The
      animation is generated in Section Animations“ / Examples“ of the online plot
                                         ”              ”
      documentation.
      Figure 10 visualizes the vector field ⃗v (x, y) = (sin(3 π y), sin(3 π x)).
D   Comments on the Graphics Gallery
                       Figure 11 shows three solution curves of an ODE inside the directional vector
                       field associated with the ODE. See the examples on the help page of
                       plot::VectorField2d.
                       Figure 12 shows several rotated copies of a function graph. See the examples on
                       the help page of plot::Rotate2d.
                       Figure 13 shows the Mandelbrot set together with two blow ups of regions of
                       special interest. See the examples on the help page of plot::Density.
                       Figure 14 shows a bar plot of statistical data. See the examples on the help page
                       of plot::Bars2d.
                       Figure 15 shows the image of a rectangle in the complex plane under the map
                       z → sin(z 2 ). See the examples on the help page of plot::Conformal.
                       Figure 16 shows some elliptic curves generated as a contour plot. See the
                       examples on the help page of plot::Implicit2d.
                       Figure 17 shows the Feigenbaum diagram of the logistic map. See the examples
                       on the help page of plot::PointList2d.
                                                            √
                       Figure 18 shows Bessel functions Jν ( x2 + y 2 ) with ν = 0, 4, 8. See the
                       examples on the help page of plot::Function3d.
                       Figure 19 shows 3D function plots with coordinate grid lines. See the examples
                       on the help page of the graphical attribute GridVisible.
                       Figure 20 shows “Klein’s bottle” (a famous topological object). This surface does
                       not have an orientation; there is no “inside” and no “outside” of this object. See
                       the examples on the help page of plot::Surface.
                       Figure 21 models various snails using plot::Surface (by Maike Kramer-Jka).
                       Figure 22 demonstrates the re-construction of an object with rotational
                       symmetry from measurements of its radius at various points. See page 11-44.
                       Figure 23 shows the solution set of the equation z 2 = sin(z − x2 · y 2 ) in 3D. See
                       the examples on the help page of plot::Implicit3d.
                       Figure 24 shows the “Lorenz attractor.” See page 11-116.
    D-2
                                                                                              Index
#                                                               _and . . . . . . . . . . . . . . . . . . . . . . see and
                                                                _assign . . . . . . . . . . . . . . . . . . 4-9, A-9
! .  ..   . . . . . . . . . . . . . . . . . . . . . see fact
              .
                                                                _concat . . . 4-16, 4-17, 4-30, 4-49, A-15
".   ..   .   .
            . . . . . . . . . . . . . . . . . . see strings
                                                                _concat . . . . . . . . . . . . . . . . . . . . . 4-10
$.   ..   .   .
            . . . . . . . . . . . . . . . . . . 4-13, 4-18
                                                                _divide . . . . . . . . . . . . . 4-13, 4-15, 4-16
'.   ..   .   .
            . . . . . . . . . . . . . . . 2-12, 2-21, 7-2
                                                                _equal . . . . . . . . . . . . . . 4-16, 14-2, 14-5
‘ .  ..   .   .
            . . . . . . . . . . . . . . . . . . . . . . . 4-8
                                                                _exprseq . . . . . . . . . . . . . . . . . 4-16, 4-21
*.   ..   . . . . . . . . . . . . . . . . . . . . see _mult
              .
                                                                _fconcat . . . . . . . . . . . . . . . . . . . . . see @
+.   ..   . . . . . . . . . . . . . . . . . . . . see _plus
              .
                                                                _fnest . . . . . . . . . . . . . . . . . . . . . see @@
-.   ..   . . . . . . see _negate and _subtract
              .
                                                                _fnest . . . . . . . . . . . . . . . . . . . . . . . 4-16
--> .     .   .
            . . . . . . . . . . . . . . . . . . 4-14, 4-52
                                                                _for . . . . . . . . . . . . . . . . . . . . . . . . . 15-5
-> . .    .   .
             2-16, 2-21, 2-24–2-26, 2-28, 4-14,
                                                                _if . . . . . . . . . . . . . . . . . . . . . . . . . . 16-3
                 4-52, 4-65, 5-8, 6-3, 7-2, 8-13,
                                                                _index . . . . . . . . . . . . . . . . . . . . . . 4-29
            10-4, 16-3, 17-1, 17-6, 17-27, 17-31,
                                                                _intersect . . . . . . . . . . . . see intersect
               A-3, A-4, A-11, A-16, A-19, A-35,
                                                                _leequal . . . . . . . . . . . . . . . . . . . . . . 4-14
                                               A-36, A-44
                                                                _less . . . . . . . . . . 4-14, 4-16, 14-2, A-14
. . . . . . . . . see _concat and concatenation
                                                                _mult . . 4-13, 4-16, 4-21, 4-33, 6-6, 14-2,
.. . . . . . . . . . . see expressions, range (..)
                                                                                                                     A-10
... . . . . . . . . . . . . . . . . . . . . . . . see hull
                                                                _negate . . . . . . . . . . . . . . . . . . . . . 4-13
/ . . . . . . . . . . . . . . . . . . . . . . see _divide
                                                                _plus . 4-13, 4-16, 4-17, 4-21, 4-22, 4-33,
/* ... */ . . . . . . . . . . . . . see comments
                                                                                  4-34, 6-6, 14-2, 17-12, A-10
// . . . . . . . . . . . . . . . . . . . see comments
                                                                _power  4-13, 4-16, 4-17, 4-21, 4-33, 9-13,
: . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3
                                                                                                                     14-2
:= . . . . . . . . . . . . . . . . . . . see assignment
                                                                _seqgen . . . . . . . . . . . . 4-15, 4-16, 4-24
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3
                                                                _subtract . . . . . . . . . . . 4-13, 4-16, A-44
< . . . . . . . . . . . . . . . . . . . . . . . . see _less
                                                                _unequal . . . . . . . . . . . . . . . . . . . . . . 4-13
<= . . . . . . . . . . . . . . . . . . . . see _leequal
                                                                _union . . . . . . . . . . . . . . . . . . 4-16, 4-17
<> . . . . . . . . . . . . . . . . . . . . see _unequal
= . . . . . . . . . . . . . . . . . . . . . . . see _equal
> . . . . . . . . . . . . . . . . . . . . . . . . see _less     A
>= . . . . . . . . . . . . . . . . . . . . see _leequal
                                                                abbreviation . . . . . . . . . . . see assignment
? . . . . . . . . . . . . . . . . . . . . . . . . . see help
                                                                abs . . . . . . . . . . . . . 2-10, 4-7, 9-24, A-41
@ . 4-15, 4-52, 4-58, 7-2, A-19, A-37, A-44
                                                                addition theorems . . . . . . . . . . . 2-14, 9-5
@@ . . . . . . . . . . . . . . . . . 4-15, 4-52, 4-58
                                                                algebraic structures . . . . . . . . . 4-60–4-63
$ . . . . 2-23, 2-24, 2-26, 2-28, 4-17, 4-24,
                                                                alias . . . . . . . . . . . . . . . . . . . . . . . A-24
                 4-28, 4-41, 6-7, 7-2, 10-1–10-4,
                                                                anames . . . . . . . . . . . . . 4-10, 4-51, A-15
         14-5, 17-23, A-3, A-4, A-7, A-9–A-11,
                                                                and . . . . . . . . . . . . . . . . 4-16, 4-18, A-14
           A-14–A-16, A-24, A-25, A-34–A-37
                                                                and . . . 4-14, 4-23, 4-47, 16-2, 17-42, A-9,
% . . . . 2-3, 2-13, 2-17, 2-19, 4-17, 5-7, 8-2,
                                                                                                                    A-48
          8-9, 9-3, 9-12, 9-17, 13-6, A-3, A-4,
                                                                animations . . . . . . . . . . . . . . . . . . . . .
                    A-15, A-16, A-19, A-24, A-26,
                                                                       . . . . 11-6, 11-22, 11-34, 11-64–11-79
                             A-28–A-30, A-33, A-36
                                                                     examples . . . . . . . . . . . . 11-77–11-79
^ . . . . . . . . . . . . . . . . . . . . . . . see _power
Index
        Index-2
                                                                                                                           Index
                                                                                                                    Index-3
Index
        Index-4
                                                                                                                           Index
                                                                                                                    Index-5
Index
        Index-6
                                                                                                                     Index
                                                                                                               Index-7
Index
        Index-8
                                                                                                                            Index
L                                                            lists . . . . . . . . . . . . . . . . . . . . . 4-28–4-35
                                                                    applying a function (map) . . . . . . 4-31
Landau symbol (O) . . . . . . . . . 4-56, A-18
                                                                    combining ∼ (zip) . . . . . . . . . . 4-33
last . . . . . . . . . . . . . . . . . . . . . . . . see %
                                                                    empty list . . . . . . . . . . . . . . . . . 4-28
last
                                                                    selecting according to properties
       evaluation of ∼ . . . . . . . . . . . . . . 13-7
                                                                      (select) . . . . . . . . . . . . . . . . . 4-32
last . . . . . . . . . . . . . . . . 5-7, 13-6, A-16
                                                                    splitting according to properties
Laurent series . . . . . . . . . . . . . . . . . 4-58
                                                                      (split) . . . . . . . . . . . . . . . . . . 4-32
legends . . . . . . . . . . . . . . . . . 11-83–11-86
                                                             ln . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-7
length . . . . . . . . . . . . . 4-51, A-15, A-34
                                                             local . . . . . . . . . . . . . . . . . . . . . . . . 17-9
LEVEL . . . . . . . . . . . . . . . . . . . . . . . . 5-6
                                                             local variables (local) . . . . . . . 17-9–17-13
level . . . . . . . . . . . . . . 5-5, 17-30, A-26
                                                                    formal parameters . . . . . . . . . . 17-27
library . . . . . . . . . . . . . . . . . . . . . 3-1–3-6
                                                                    uninitialized ∼ . . . . . . . . . . . . . 17-11
      exporting a ∼ (use) . . . . . . . . . . 3-4
                                                             log . . . . . . . . . . . . . . . . . . . . . . . . . 4-96
      for color names (RGB) . . . . . . . . 11-61
                                                             logarithm (ln, log) . . . . . . . . . . 2-7, 4-96
      for data structures (Dom) . . . . . . 4-60
                                                             logical formula . . . . . . . . . . . . . . . . 17-42
      for external formats (generate) . . 13-3
                                                             long arrow operator (-->) . . . . . . . . . 4-52
      for Gröbner bases (groebner) . . 4-89
                                                             loops . . . . . . . . . . . . . . . . . . . . . 15-1–15-5
      for input (import) . . . . . . . . . . . 12-6
                                                                    aborting ∼ (break) . . . . . . . . . . . 15-4
      for linear algebra (linalg) . . . . 4-74
                                                                    for . . . . . . . . . . . . . . . . . . . . . . 15-1
      for number theory (numlib) . . . . .
                                                                    repeat . . . . . . . . . . . . . . . . . . . . 15-3
        . . . . . . . . . . . . . . . . . . . . 2-28, 3-2
                                                                    return value . . . . . . . . . . . . . . . . 15-5
      for numerical algorithms (numeric)
                                                                    skipping commands (next) . . . . . 15-4
        . . . . . . . . . . . . . . . . . . . . 3-4, 4-74
                                                                    while . . . . . . . . . . . . . . . . . . . . 15-3
      for orthogonal polynomials
                                                             Lorenz attractor . . . . . . . . . . . . . . . . 11-99
       (orthpoly) . . . . . . . . . . . . . . . A-17
      for statistics (stats) . . . . . . . . . 10-2
      for strings (stringlib) . . . . . . . 4-50             M
      for type specifiers (Type) . . . . . . . .
                                                             manipulating expressions . . . . . . 9-1–9-24
        . . . . . . . . . . . . . . 14-4, 17-20, A-39
                                                             map . . . 2-19, 4-17, 4-31, 4-34, 4-38, 4-42,
      information on a ∼ (? and info) . 3-2
                                                                            4-46, 4-71, 5-7, 8-4, 8-9, 8-11,
      standard ∼ . . . . . . . . . . . . . . . . . 3-6
                                                                      17-40, A-4, A-10, A-13, A-15, A-28,
limit . . 2-7, 2-16, 2-21, 2-22, 4-99, A-34
                                                                                                A-34, A-37, A-44
      one-sided . . . . . . . . . . . . . . . . . . 2-21
                                                             maps . . . . . . . . . . . . . . . . . . see functions
limit computation (limit) . . . . . . . . 2-16
                                                             mathematical objects . . . . . . . . . . . . . . 1-3
linalg (library for linear algebra)
                                                             matrices . . . . . . . . . . . . . . . . . 4-64–4-80
      ∼::charpoly . . . . . . . . . 4-75, A-22
                                                                  characteristic polynomial
      ∼::det . . . . . . . . . . . . . . 2-18, A-20
                                                                    (linalg::charpoly) . . . 4-75, A-22
      ∼::eigenvalues . . 4-75, 4-77, A-22
                                                                  computing with ∼ . . . . . . 4-70–4-72
      ∼::eigenvectors . . . . . . . . . . A-23
                                                                  default coefficient ring
      ∼::invhilbert . . . . . . . . . . . . 4-97
                                                                    (Dom::ExpressionField) . . . . . 4-68
      ∼::isPosDef . . . . . . . . . . . . . . 9-23
                                                                  determinant (linalg::det) . . . . 2-18
linear algebra (linalg) . . . . . . . . . . . 4-74
                                                                  diagonal ∼ . . . . . . . . . . . . . . . . 4-67
linefeed . . . . . . . . . . . . . . . . . . . . . . . 2-2
                                                                  eigenvalues
                                                                                                                     Index-9
Index
        Index-10
                                                                                                                         Index
                                                                                                                 Index-11
Index
        Index-12
                                                                                                                       Index
                                                                                                               Index-13
Index
        Index-14
                                                                                                                          Index
                                                                                                                  Index-15
Index
        Index-16
                                                                                                                                   Index
U
unassume .    .   .   .....   . . . . . . . . . . . . . . 9-21
undefined     .   .   .....   . . . . . . . . . 4-99, 5-11
union . . .   .   .   4-37,   4-39, 4-95, A-13, A-36
UNKNOWN .     .   .   .....   . . . . 4-32, 4-38, 4-47
unknowns .        .   .....   . . . . . . . see identifiers
unprotect .       .   .....   . . . . . . . . . . . . . 4-10
use . . . . . .   .   .....   . . . . . . . . . 3-4, 11-62
Index-17