%mathpiper,def="*"

/* Multiplication */

50  # x_IsNumber * y_IsNumber <-- MultiplyN(x,y);
100 #  1  * _x  <-- x;
100 # _x  *  1  <-- x;
100 # (_f  * _x)_(f= -1)  <-- -x;
100 # (_x  * _f)_(f= -1)  <-- -x;
105 # (f_IsNegativeNumber * _x)  <-- -(-f)*x;
105 # (_x * f_IsNegativeNumber)  <-- -(-f)*x;

95 # x_IsMatrix * y_IsMatrix <--
[
   Local(i,j,k,row,result);
   result:=ZeroMatrix(Length(x),Length(y[1]));
   For(i:=1,i<=Length(x),i++)
   For(j:=1,j<=Length(y),j++)
   For(k:=1,k<=Length(y[1]),k++)
   [
     row:=result[i];
     row[k]:= row[k]+x[i][j]*y[j][k];
   ];
   result;
];


96 # x_IsMatrix * y_IsList <--
[
   Local(i,result);
   result:={};
   For(i:=1,i<=Length(x),i++)
   [ DestructiveInsert(result,i,Dot(x[i], y)); ];
   result;
];


97 # (x_IsList * y_IsNonObject)_Not(IsList(y)) <-- y*x;
98 # (x_IsNonObject * y_IsList)_Not(IsList(x)) <--
[
   Local(i,result);
   result:={};
   For(i:=1,i<=Length(y),i++)
   [ DestructiveInsert(result,i,x * y[i]); ];
   result;
];


50  # _x * Undefined <-- Undefined;
50  # Undefined * _y <-- Undefined;


100  # 0 * y_IsInfinity <-- Undefined;
100  # x_IsInfinity * 0 <-- Undefined;

101 # 0    * (_x) <-- 0;
101 # (_x) *    0 <-- 0;

100 # x_IsNumber * (y_IsNumber * _z) <-- (x*y)*z;
100 # x_IsNumber * (_y * z_IsNumber) <-- (x*z)*y;

100 # (_x * _y) * _y <-- x * y^2;
100 # (_x * _y) * _x <-- y * x^2;
100 # _y * (_x * _y) <-- x * y^2;
100 # _x * (_x * _y) <-- y * x^2;
100 # _x * (_y / _z) <-- (x*y)/z;
// fractions
100 # (_y / _z) * _x <-- (x*y)/z;
100 # (_x * y_IsNumber)_Not(IsNumber(x)) <-- y*x;

100 # (_x) * (_x) ^ (n_IsConstant) <-- x^(n+1);
100 # (_x) ^ (n_IsConstant) * (_x) <-- x^(n+1);
100 # (_x * _y)* _x ^ n_IsConstant <-- y * x^(n+1);
100 # (_y * _x)* _x ^ n_IsConstant <-- y * x^(n+1);
100 # Sqrt(_x) * (_x) ^ (n_IsConstant) <-- x^(n+1/2);
100 # (_x) ^ (n_IsConstant) * Sqrt(_x) <-- x^(n+1/2);
100 # Sqrt(_x) * (_x) <-- x^(3/2);
100 # (_x) * Sqrt(_x) <-- x^(3/2);

105 # x_IsNumber * -(_y) <-- (-x)*y;
105 # (-(_x)) * (y_IsNumber) <-- (-y)*x;

106 # _x * -(_y) <-- -(x*y);
106 # (- _x) * _y <-- -(x*y);

107 # -( (-(_x))/(_y)) <-- x/y;
107 # -( (_x)/(-(_y))) <-- x/y;


250  # x_IsNumber * y_IsInfinity <-- Sign(x)*y;
250  # x_IsInfinity * y_IsNumber <-- Sign(y)*x;


/* Note: this rule MUST be past all the transformations on
 * matrices, since they are lists also.
 */
230 # (aLeft_IsList * aRight_IsList)_(Length(aLeft)=Length(aRight)) <--
	 Map("*",{aLeft,aRight});
// fractions
242 # (x_IsInteger / y_IsInteger) * (v_IsInteger / w_IsInteger) <-- (x*v)/(y*w);
243 #  x_IsInteger * (y_IsInteger / z_IsInteger) <--  (x*y)/z;
243 #  (y_IsInteger / z_IsInteger) * x_IsInteger <--  (x*y)/z;

400 # (_x) * (_x) <-- x^2;

%/mathpiper


%mathpiper_docs,name="*",categories="Operators"
*CMD * --- arithmetic multiplication
*STD
*CALL

	x*y
Precedence:
*EVAL PrecedenceGet("*")

*PARMS

{x} and {y} -- objects for which arithmetic multiplication is defined

*DESC

The multiplication operator can work on integers,
rational numbers, complex numbers, vectors, matrices and lists.

This operator is implemented in the standard math library (as opposed
to being built-in). This means that they can be extended by the user.

*E.G.

In> 2*3
Result: 6;
%/mathpiper_docs
