* -- multiply expressions
Introductionx * y * ... computes the product of x,
y etc.
Call(s)
x * y * ... _mult(x, y...)
Parametersx, y, ... |
- | arithmetical expressions,
polynomials of type DOM_POLY, or sets |
Returnsan arithmetical expression, a polynomial, or a set.
x, y, , ...
Related
Functions_invert, _negate, product, ^, /, +, -, poly, Pref::timesDot
Detailsx * y * ... is equivalent to the function call
_mult(x, y, ...).Type::Numeric are automatically
combined to a single number._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.x/y is internally represented as x
* (1/y) = _mult(x, _power(y, -1)). See _divide for details._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.DOM_POLY are multiplied by
*, if they have the same indeterminates and the same
coefficient ring. Use multcoeffs to multiply
polynomials with scalar factors.X, Y, the product X
* Y is the set {x * y; x in X; y in Y}._mult is a function of the system kernel.
Example
1Numerical terms are simplified automatically:
>> 3 * x * y * (1/18) * sin(4) * 4
2 x y sin(4)
------------
3
The ordering of the terms of a product is not necessarily the same as on input:
>> x * y * 3 * z * a * b * c
3 a b c x y z
Internally, this product is a symbolic call of
_mult:
>> op(%, 0), type(%)
_mult, "_mult"
Note that the screen output does not necessarily reflect the internal order of the terms in a product:
>> op(%2)
a, b, c, x, y, z, 3
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
12 x y
>> op(%)
x, y, 12
Example
2The 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)
2432902008176640000
E.g., it is easy to multiply all elements in a set:
>> S := {a, b, 1, 2, 27}: _mult(op(S))
54 a b
The following command ``zips'' two lists by multiplying corresponding elements:
>> L1 := [1, 2, 3]: L2 := [a, b, c]: zip(L1, L2, _mult)
[a, 2 b, 3 c]
>> delete S, L1, L2:
Example
3Polynomials 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])
4 3
poly(x + x + x - 1, [x])
Symbolic products 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)
Multiplication of polynomials with scalar factors cannot
be achieved with *:
>> 2 * y * poly(x, [x])
2 poly(x, [x]) y
Use multcoeffs instead:
>> multcoeffs(poly(x^2 - 2, [x]), 2*y)
2
poly((2 y) x - 4 y, [x])
Example
4For finite sets X, Y, the
product X * Y is the set {x * y; x in X; y in
Y}:
>> {a, b, c} * {1, 2}
{a, b, c, 2 a, 2 b, 2 c}
>> 2 * {a, b, c} * c
2
{2 a c, 2 b c, 2 c }
Example
5Various 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
+- -+ +- -+
| 34, 37 | | 43, 64 |
| |, | |
| 78, 85 | | 51, 76 |
+- -+ +- -+
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)
Dom::Matrix(Dom::Integer), Dom::Matrix(Dom::Rational)
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
+- -+ +- -+
| 34, 38 | | 43, 64 |
| |, | |
| 78, 87 | | 105/2, 78 |
+- -+ +- -+
>> domtype(x * y), domtype(y * x)
Dom::Matrix(Dom::Rational), Dom::Matrix(Dom::Rational)
>> delete x, y:
Example
6This 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
6 x y z
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
userinfo(10, "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:
setuserinfo(myString::_mult, 10):
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
stringstringstringstringstringstring
Only products of integers and myString
objects are allowed:
>> 3/2 * myString("a ") * myString("string")
Info: myString::_mult called with the arguments:, 3/2, a , str\
ing
FAIL
>> delete myString, y, z: