Previous Page Next Page Contents

* -- multiply expressions

Introduction

x * y * ... computes the product of x, y etc.

Call(s)


x * y * ... _mult(x, y...)

Parameters

x, y, ... - arithmetical expressions, polynomials of type DOM_POLY, or sets

Returns

an arithmetical expression, a polynomial, or a set.

Overloadable:

x, y, , ...

Related Functions

_invert, _negate, product, ^, /, +, -, poly, Pref::timesDot

Details

Example 1

Numerical 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 2

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)
                            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 3

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])
                              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 4

For 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 5

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
                        +-        -+  +-        -+
                        |  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 6

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
                                  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:

Changes




Do you have questions or comments?


Copyright © SciFace Software GmbH & Co. KG 2000