+
-- add expressionsx + y + ...
computes the sum of x
,
y
etc.
x + y + ... _plus(x, y...)
x, y, ... |
- | arithmetical expressions,
polynomials of type DOM_POLY , or sets |
an arithmetical expression, a polynomial, or a set.
x
, y
, ,
...
_invert
, _negate
, ^
, /
, *
, -
, poly
, sum
, Pref::keepOrder
x + y + ...
is equivalent to the function call
_plus(x, y, ...)
.Type::Numeric
are automatically
combined to a single number.Pref::keepOrder
. See also the
documentation for print
._plus
accepts an arbitrary number of arguments. In
conjunction with the sequence operator $
, this function is the recommended tool
for computing finite sums. Cf. example 2. The
function sum
may also
serve for computing such sums. However, sum
is designed for the computation of
symbolic and infinite sums. It is slower than _plus
.x - y
is internally represented as x +
y*(-1)
= _plus(x, _mult(y, -1))
. See _subtract
for details._plus
by an appropriate slot
"_plus"
. Sums involving elements of library domains are
processed as follows:
A sum x + y + ...
is searched for elements of library
domains from left to right. Let z
be the first term that
is not of one of the basic types provided by the kernel (numbers,
expressions, etc.). If the domain d
= z::dom
= domtype(z)
has a slot
"_plus"
, it is called in the form d::_plus(x, y,
...)
. The result returned by d::_plus
is the result
of x + y + ...
.
Users should implement the slot d::_plus
of their
domains d
according to the following convention:
d
, an appropriate sum of
type d
should be returned.d
, the slot should return FAIL
.d
, but can be converted to type d
. Such terms
should be converted only if the mathematical semantics is obvious to
any user who uses this domain as a 'black box' (e.g., integers may be
regarded as rational numbers because of the natural mathematical
embedding). If in doubt, the "_plus"
method should return
FAIL
instead of using
implicit conversions. If implicit conversions are used, they must be
well-documented.Most of the library domains in MuPAD's standard installation comply with this convention.
_plus()
returns the number 0.DOM_POLY
are added by
+
, if they have the same indeterminates and the same
coefficient ring.X
, Y
, the sum X +
Y
is the set {x + y; x in X; y in Y}._plus
is a function of the system kernel.Numerical terms are simplified automatically:
>> 3 + x + y + 2*x + 5*x - 1/2 - sin(4) + 17/4
8 x + y - sin(4) + 27/4
The ordering of the terms of a sum is not necessarily the same as on input:
>> x + y + z + a + b + c
a + b + c + x + y + z
>> 1 + x + x^2 + x^10
2 10 x + x + x + 1
Internally, this sum is a symbolic call of
_plus
:
>> op(%, 0), type(%)
_plus, "_plus"
The functional equivalent _plus
of the
operator +
is a handy tool for computing finite sums. In
the following, the terms are generated via the sequence operator
$
:
>> _plus(i^2 $ i = 1..100)
338350
E.g., it is easy to add up all elements in a set:
>> S := {a, b, 1, 2, 27}: _plus(op(S))
a + b + 30
The following command ``zips'' two lists by adding corresponding elements:
>> L1 := [a, b, c]: L2 := [1, 2, 3]: zip(L1, L2, _plus)
[a + 1, b + 2, c + 3]
>> delete S, L1, L2:
Polynomials of type DOM_POLY
are added by
+
, if they have the same indeterminates and the same
coefficient ring:
>> poly(x^2 + 1, [x]) + poly(x^2 + x - 1, [x])
2 poly(2 x + x, [x])
Symbolic sums are returned if the indeterminates or the coefficient rings do not match:
>> poly(x, [x]) + poly(x, [x, y])
poly(x, [x]) + poly(x, [x, y])
>> poly(x, [x]) + poly(x, [x], Dom::Integer)
poly(x, [x]) + poly(x, [x], Dom::Integer)
For finite sets X
, Y
, the sum
X + Y
is the set {x + y; x in X; y in Y}:
>> {a, b, c} + {1, 2}
{a + 1, a + 2, b + 1, b + 2, c + 1, c + 2}
Various library domains such as matrix domains overload _plus
:
>> x := Dom::Matrix(Dom::Integer)([1, 2]): y := Dom::Matrix(Dom::Rational)([2, 3]): x + y, y + x
+- -+ +- -+ | 3 | | 3 | | |, | | | 5 | | 5 | +- -+ +- -+
If the terms in a sum x + y
are of
different type, the first term x
tries to convert
y
to the data type of x
. If successful, the
sum is of the same type as x
. In the previous example,
x
and y
have different types (both are
matrices, but the component domains differ). Hence the sums x +
y
and y + x
differ syntactically, because they
inherit their type from the first term:
>> bool(x + y = y + x)
FALSE
>> domtype(x + y), domtype(y + x)
Dom::Matrix(Dom::Integer), Dom::Matrix(Dom::Rational)
If x
does not succeed to convert
y
, then FAIL
is returned. In the following call, the component 2/3
cannot be converted to an integer:
>> y := Dom::Matrix(Dom::Rational)([2/3, 3]): x + y
FAIL
>> delete x, y:
This example demonstrates how to implement a slot "_plus"
for a domain. The following
domain myString
is to represent character strings. The sum
of such strings is to be the concatenation of the strings.
The "new"
method uses expr2text
to convert any
MuPAD object to a string. This string is the internal
representation of elements of myString
. The
"print"
method turns this string into the screen
output:
>> myString := newDomain("myString"): myString::new := proc(x) begin if args(0) = 0 then x := "": end_if; case domtype(x) of myString do return(x); of DOM_STRING do return(new(dom, x)); otherwise return(new(dom, expr2text(x))); end_case end_proc: myString::print := x -> extop(x, 1):
Without a "_plus"
method, the system
function _plus
handles elements of this domain like any
symbolic object:
>> y := myString(y): z := myString(z): 1 + x + y + z + 3/2
x + y + z + 5/2
Now, we implement the "_plus"
method. It
checks all arguments. Arguments are converted, if they are not of type
myString
. Generally, such an implicit conversion should be
avoided. In this case, however, any object has a corresponding string
representation via expr2text
and an implicit
conversion is implemented. Finally, the sum of myString
objects is defined as the concatenation of the internal strings:
>> myString::_plus := proc() local n, Arguments, i; begin userinfo(10, "myString::_plus called with the arguments:", args()): n := args(0): Arguments := [args()]; for i from 1 to n do if domtype(Arguments[i]) <> myString then // convert the i-th term to myString Arguments[i] := myString::new(Arguments[i]): end_if; end_for: myString::new(_concat(extop(Arguments[i], 1) $ i = 1..n)) end_proc: setuserinfo(myString::_plus, 10):
Now, myString
objects can be added:
>> myString("This ") + myString("is ") + myString("a string")
Info: myString::_plus called with the arguments:, This , is , \ a string This is a string
In the following sum, y
and z
are elements of myString
. The term y
is the
first term that is an element of a library domain. Its
"_plus"
method is called and concatenates all terms to a
string of type myString
:
>> 1 + x + y + z + 3/2;
Info: myString::_plus called with the arguments:, 1, x, y, z, \ 3/2 1xyz3/2
>> delete myString, y, z: