Documentation |
Multiply expressions
This functionality does not run in MATLAB.
x * y * ... _mult(x, y, …)
x * y * ... computes the product of x, y etc.
x * y * ... is equivalent to the function call _mult(x, y, ...).
All terms that are numbers of type Type::Numeric are automatically combined to a single number.
The terms of a symbolic product may be rearranged internally if no term belongs to a library domain that overloads _mult: on terms composed of kernel domains (numbers, identifiers, expressions etc.), multiplication is assumed to be commutative. Cf. Example 1.
Via overloading, the user can implement a non-commutative product for special domains.
_mult accepts an arbitrary number of arguments. In conjunction with the sequence operator $, this function is the recommended tool for computing finite products. Cf. Example 2. The function product may also serve for computing such products. However, product is designed for the computation of symbolic and infinite products. It is slower than _mult.
The quotient x/y is internally represented as x * (1/y) = _mult(x, _power(y, -1)). See _divide for details.
Many library domains overload _mult by an appropriate slot"_mult". Products involving elements of library domains are processed as follows:
A product 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"_mult", it is called in the form d::_mult(x, y, ...). The result returned by d::_mult is the result of x * y * ....
_mult() returns the number 1.
Polynomials of type DOM_POLY are multiplied by *, if they have the same indeterminates and the same coefficient ring. Use multcoeffs to multiply polynomials with scalar factors.
For finite sets X, Y, the product X * Y is the set .
Equalities, inequalities, and comparisons can be multiplied with one another or with arithmetical expressions. The results of such combinations are demonstrated in Example 5.
Numerical terms are simplified automatically:
3 * x * y * (1/18) * sin(4) * 4
The ordering of the terms of a product is not necessarily the same as on input:
x * y * 3 * z * a * b * c
Internally, this product is a symbolic call of _mult:
op(%, 0), type(%)
Note that the screen output does not necessarily reflect the internal order of the terms in a product:
op(%2)
In particular, a numerical factor is internally stored as the last operand. On the screen, a numerical factor is displayed in front of the remaining terms:
3 * x * y * 4
op(%)
The functional equivalent _mult of the operator * is a handy tool for computing finite products. In the following, the terms are generated via the sequence operator $:
_mult(i $ i = 1..20)
E.g., it is easy to multiply all elements in a set:
S := {a, b, 1, 2, 27}: _mult(op(S))
The following command "zips" two lists by multiplying corresponding elements:
L1 := [1, 2, 3]: L2 := [a, b, c]: zip(L1, L2, _mult)
delete S, L1, L2:
Polynomials of type DOM_POLY are multiplied by *, if they have the same indeterminates and the same coefficient ring:
poly(x^2 + 1, [x]) * poly(x^2 + x - 1, [x])
If the indeterminates or the coefficient rings do not match, _mult returns an error:
poly(x, [x]) * poly(x, [x, y])
Error: The argument is invalid. [_mult]
poly(x, [x]) * poly(x, [x], Dom::Integer)
Error: The argument is invalid. [_mult]
Using *, you can multiply polynomials by scalar factors:
2 * y * poly(x, [x])
Use multcoeffs instead:
multcoeffs(poly(x^2 - 2, [x]), 2*y)
For finite sets X, Y, the product X * Y is the set :
{a, b, c} * {1, 2}
Note that complex numbers of type DOM_INT, DOM_RAT, DOM_COMPLEX, DOM_FLOAT, and identifiers are implicitly converted to one-element sets:
2 * {a, b, c}
a * {b, c}, PI * {3, 4}
Multiplying by a constant expression is performed on both sides of an equation:
(a = b) * c
For inequalities, this step is only performed if the constant is known to be non-zero:
assume(d <> 0): (a <> b) * c, (a <> b) * d; delete d:
The multiplication of a comparison with a constant is only defined for real numbers. Even for these, the result depends on the sign of the constant, since multiplication with a negative constant changes the direction of the comparison:
(a < b) * 2, (a < b) * (-3)
(a < b) * I
Error: Inequalities must not be multiplied by complex numbers. [_less::_mult]
(a < b) * c, (a <= b) * c
Multiplication of two equalities is performed by multiplying the left hand sides and the right hand sides separately:
(a = b) * (c = d)
Inequalities cannot be multiplied with one another or with comparisons; multiplication with equalities is, however, defined, if at least one operand of the equation is known to be non-zero:
assume(d <> 0): (a <> b) * (c = d); delete d:
In other cases, the product is not expanded:
delete c, d: (a <> b) * (c = d)
Multiplication of comparisons with equalities and comparisons is performed similar to the cases above:
assume(c > 0): (a < b) * (c = d); delete c:
(a <= b) * (c <= d)
Various library domains such as matrix domains overload _mult. The multiplication is not commutative:
x := Dom::Matrix(Dom::Integer)([[1, 2], [3, 4]]): y := Dom::Matrix(Dom::Rational)([[10, 11], [12, 13]]): x * y, y * x
If the terms in x * y are of different type, the first term x tries to convert y to the data type of x. If successful, the product 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 x * y and y * x have different types that is inherited from the first term:
domtype(x * y), domtype(y * x)
If x does not succeed to convert y, then y tries to convert x. In the following call, the component 27/2 cannot be converted to an integer. Consequently, in x * y, the term y converts x and produces a result that coincides with the domain type of y:
y := Dom::Matrix(Dom::Rational)([[10, 11], [12, 27/2]]): x * y, y * x
domtype(x * y), domtype(y * x)
delete x, y:
This example demonstrates how to implement a slot"_mult" for a domain. The following domain myString is to represent character strings. Via overloading of _mult, integer multiples of such strings should produce the concatenation of an appropriate number of copies of the string.
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 "_mult" method, the system function _mult handles elements of this domain like any symbolic object:
y := myString(y): z := myString(z): 4 * x * y * z * 3/2
Now, we implement the "_mult" method. It uses split to pick out all integer terms in its argument list and multiplies them. The result is an integer n. If there is exactly one other term left (this must be a string of type myString), it is copied n times. The concatenation of the copies is returned:
myString::_mult:= proc() local Arguments, intfactors, others, dummy, n; begin print(Unquoted, "Info: myString::_mult called with the arguments:", args()); Arguments := [args()]; // split the argument list into integers and other factors: [intfactors, others, dummy] := split(Arguments, testtype, DOM_INT); // multiply all integer factors: n := _mult(op(intfactors)); if nops(others) <> 1 then return(FAIL) end_if; myString::new(_concat(extop(others[1], 1) $ n)) end_proc:
Now, integer multiples of myString objects can be constructed via the * operator:
2 * myString("string") * 3
Info: myString::_mult called with the arguments:, 2, string, 3
Only products of integers and myString objects are allowed:
3/2 * myString("a ") * myString("string")
3 Info: myString::_mult called with the arguments:, -, a , string 2
delete myString, y, z:
x, y, … |
arithmetical expressions, polynomials of type DOM_POLY, sets, equations, inequalities, or comparisons |