Element-wise Operators - Maple Programming Help

Home : Support : Online Help : Programming : Operations : Operators : operators/elementwise

Element-wise Operators

Description

 • An element-wise operation allows you to distribute the operation over the elements of a data container.  The syntax for this is to use a tilde (~) after the given operator or function name.
 > <1,2,3> *~ <4,5,6>;
 $\left[\begin{array}{c}{4}\\ {10}\\ {18}\end{array}\right]$ (1)
 • An element-wise function allows you to apply a function to the elements of a data container.  As with any function call, you must use parentheses.
 > sin~(<1,2,3>);
 $\left[\begin{array}{c}{\mathrm{sin}}{}\left({1}\right)\\ {\mathrm{sin}}{}\left({2}\right)\\ {\mathrm{sin}}{}\left({3}\right)\end{array}\right]$ (2)
 > f:=x->x^2:
 > f~();
 $\left[\begin{array}{c}{{a}}^{{2}}\\ {{b}}^{{2}}\\ {{c}}^{{2}}\end{array}\right]$ (3)
 • The data container can be a list, set, table, Array, Matrix, or Vector. Details and other possibilies are discussed in the Details section below.
 • The element-wise operators in Maple are:

 +~ addition or unary plus (prefix) -~ subtraction or unary minus (prefix) *~ multiplication /~ division ^~ exponentiation mod~ modulo !~ factorial (unary postfix) <~ less than <=~ less than or equal >~ greater than >=~ greater than or equal =~ equal <>~ not equal @~ composition @@~ repeated composition ||~ concatenation operator .~ non-commutative multiplication ::~ type operator and~ logical and or~ logical or xor~ exclusive or implies~ implication not~ logical not (unary prefix) union~ set union subset~ subset intersect~ set intersection minus~ set difference in~ set or list membership & ~ neutral operator &name ~ neutral operator (unary prefix) funct~ general element-wise operator (unary postfix)

Details

 • Dimensioned container types: list, set, Array, Matrix, and Vector can be intermixed in a given operation as long as they are the same size. A table can only appear once in an argument list and can only be mixed with non-containers. For the purpose of element-wise operations, records are not considered containers.
 > [true,true,false,false] xor~ ;
 $\left[\begin{array}{c}{\mathrm{false}}\\ {\mathrm{true}}\\ {\mathrm{true}}\\ {\mathrm{false}}\end{array}\right]$ (4)
 • Non-containers are treated as single elements repeated sufficiently often to match the size of the other containers in the argument sequence.
 > <1,2,3> ^~ 2;
 $\left[\begin{array}{c}{1}\\ {4}\\ {9}\end{array}\right]$ (5)
 • Unlike map and zip, which usually apply to the operands of their given arguments, element-wise operations treat non-container data types as single elements.  For example, f~(a=b) evaluates to f(a=b), whereas map(f,a=b) breaks apart the equation applying f to each side of the equation resulting in f(x)=f(b).
 • It is never an error to use a single-element non-container in any part of an element-wise expression. If an error occurs it happens as a result of applying the base operator to one subset of the overall operation. In other words, when applying ^~, the only error that will ever be raised will come from ^, with the exception of mismatched container sizes.
 • The returned data structure will match the type of the given container. A call involving only lists will return a list. When mixed container types are present the return type will be determined according to the following precedence: object, rtable, list, set. A call involving rtables and arrays(deprecated) will result in an rtable. A call involving arrays and lists will result in an array.
 > f~([a1,a2],,c);
 $\left[\begin{array}{c}{{\mathrm{a1}}}^{{2}}\\ {{\mathrm{a2}}}^{{2}}\end{array}\right]$ (6)
 • Lists and sets are always considered to be 1-dimensional. That is, a list-of-lists is not inferred as a 2-D container.
 > [[1,2],[3,4]] +~ 2;
 $\left[\left[{1}{,}{2}\right]{+}{2}{,}\left[{3}{,}{4}\right]{+}{2}\right]$ (7)
 • An object will only be treated as a container if it exports both ?[] and upperbound.  If lowerbound is not exported then it will be assumed that the lower bounds for each dimension are 1.  If an object does not export these methods, it will be treated as a scalar.  An elementwise operation involving objects will proceed by using ?[] to extract the relevant elements into an Array, build up the result in said Array, and then attempt to call the first object's ModuleCopy constructor with the Array as an argument.  If ModuleCopy does not exist, or if it raises an error, then the result will be returned as an Array.  It is assumed that the ModuleCopy constructor uses the first argument to populate its data; if it ignores the data array, then the result will likely be incorrect.
 • Expression sequences are also treated as container types when they appear on either side of an element-wise operator.  Due to the normal flattening rules expression sequences cannot normally be used with functional notation as they are interpreted as multiple arguments.  The exception to this rule can be found when following the internal representation outlined for overloading element-wise operations.  Element-wise operators can be overloaded by binding the ~ function.  The ~ function gets called with the operation in square brackets as an index to the function name.  In order to distinguish element-wise operator calls with an expression sequence on either side of the operator, the arguments are separated by a special fence token,  $(space-dollarsign). The statement, a +~ (b,c) is recast as ~[+](a,$, b, c).  Similarly, f~(a,b, \$,1,2) is interpreted as a element-wise function call with two expression sequence arguments, (a,b), and (1,2), resulting in the sequence f(a,1),f(b,2).
 • Because ~ is allowed at the beginning of a name in Maple, white-space is required in some situations to make the meaning of a statement unambiguous.  Consider the expression (a*~b) -- this means (a  *~ b), not a * (~b).  Using parentheses or adding a space after the multiplication symbol is required to use the name ~b (tilde-b) in an expression like this.
 • The neutral operators &*~ and &+~ are currently valid, so use of element-wise &* and &+ requires a space between the neutral operator and the tilde (i.e., (a &* ~ b) is element-wise &*, and (a &*~ b) is a use of the neutral operator &*~.  This distinction is not something that can be enforced by the parser -- be careful when using element-wise &* and &+.)
 • When a non-operator expression involving tilde is not part of a function call, a symbolic representation is returned.  The underlying representation of f~ is ~[f].  These expressions retain their element-wise properties while being passed into other functions.  For example, consider the difference between map(f,[[a,b]]) and map(f~,[[a,b]).  In the first case f is applied to the sublist, [a,b], and in the second case f is applied in an element-wise fashion to the same sublist.

Examples of Element-wise Operators

 > A := <1,2,3;4,5,6;7,8,9>;
 ${A}{≔}\left[\begin{array}{ccc}{1}& {2}& {3}\\ {4}& {5}& {6}\\ {7}& {8}& {9}\end{array}\right]$ (8)
 > B := LinearAlgebra:-IdentityMatrix(3);
 ${B}{≔}\left[\begin{array}{ccc}{1}& {0}& {0}\\ {0}& {1}& {0}\\ {0}& {0}& {1}\end{array}\right]$ (9)
 > A . B;
 $\left[\begin{array}{ccc}{1}& {2}& {3}\\ {4}& {5}& {6}\\ {7}& {8}& {9}\end{array}\right]$ (10)
 > A .~ B;
 $\left[\begin{array}{ccc}{1}& {0}& {0}\\ {0}& {5}& {0}\\ {0}& {0}& {9}\end{array}\right]$ (11)
 > sin~(A);
 $\left[\begin{array}{ccc}{\mathrm{sin}}{}\left({1}\right)& {\mathrm{sin}}{}\left({2}\right)& {\mathrm{sin}}{}\left({3}\right)\\ {\mathrm{sin}}{}\left({4}\right)& {\mathrm{sin}}{}\left({5}\right)& {\mathrm{sin}}{}\left({6}\right)\\ {\mathrm{sin}}{}\left({7}\right)& {\mathrm{sin}}{}\left({8}\right)& {\mathrm{sin}}{}\left({9}\right)\end{array}\right]$ (12)
 > -~ A;
 $\left[\begin{array}{ccc}{-1}& {-2}& {-3}\\ {-4}& {-5}& {-6}\\ {-7}& {-8}& {-9}\end{array}\right]$ (13)
 > A !~;
 $\left[\begin{array}{ccc}{1}& {2}& {6}\\ {24}& {120}& {720}\\ {5040}& {40320}& {362880}\end{array}\right]$ (14)
 > myproc := proc(x) x^2; end:
 > myproc~(A);
 $\left[\begin{array}{ccc}{1}& {4}& {9}\\ {16}& {25}& {36}\\ {49}& {64}& {81}\end{array}\right]$ (15)
 > A mod~ 3;
 $\left[\begin{array}{ccc}{1}& {2}& {0}\\ {1}& {2}& {0}\\ {1}& {2}& {0}\end{array}\right]$ (16)
 > A >~ 3;
 $\left[\begin{array}{ccc}{3}{<}{1}& {3}{<}{2}& {3}{<}{3}\\ {3}{<}{4}& {3}{<}{5}& {3}{<}{6}\\ {3}{<}{7}& {3}{<}{8}& {3}{<}{9}\end{array}\right]$ (17)
 > evalb~(A >~ 3);
 $\left[\begin{array}{ccc}{\mathrm{false}}& {\mathrm{false}}& {\mathrm{false}}\\ {\mathrm{true}}& {\mathrm{true}}& {\mathrm{true}}\\ {\mathrm{true}}& {\mathrm{true}}& {\mathrm{true}}\end{array}\right]$ (18)
 > (evalb@>) ~ (A,3);
 $\left[\begin{array}{ccc}{\mathrm{false}}& {\mathrm{false}}& {\mathrm{false}}\\ {\mathrm{true}}& {\mathrm{true}}& {\mathrm{true}}\\ {\mathrm{true}}& {\mathrm{true}}& {\mathrm{true}}\end{array}\right]$ (19)
 > evalhf~(A >~ 3);
 $\left[\begin{array}{ccc}{0.}& {0.}& {0.}\\ {1.}& {1.}& {1.}\\ {1.}& {1.}& {1.}\end{array}\right]$ (20)
 > A ::~ integer;
 $\left[\begin{array}{ccc}{1}{::}{?}& {2}{::}{?}& {3}{::}{?}\\ {4}{::}{?}& {5}{::}{?}& {6}{::}{?}\\ {7}{::}{?}& {8}{::}{?}& {9}{::}{?}\end{array}\right]$ (21)
 > [true,true,false,false] and~ ;
 $\left[\begin{array}{c}{\mathrm{true}}\\ {\mathrm{false}}\\ {\mathrm{false}}\\ {\mathrm{false}}\end{array}\right]$ (22)
 > [{1,2},{3,4}] subset~ [{1,3,4,5},{1,3,4,5}];
 $\left[{\mathrm{false}}{,}{\mathrm{true}}\right]$ (23)
 > A @~ b;
 $\left[\begin{array}{ccc}{1}{@}{b}& {2}{@}{b}& {3}{@}{b}\\ {4}{@}{b}& {5}{@}{b}& {6}{@}{b}\\ {7}{@}{b}& {8}{@}{b}& {9}{@}{b}\end{array}\right]$ (24)
 > b @~ A;
 $\left[\begin{array}{ccc}{b}{@}{1}& {b}{@}{2}& {b}{@}{3}\\ {b}{@}{4}& {b}{@}{5}& {b}{@}{6}\\ {b}{@}{7}& {b}{@}{8}& {b}{@}{9}\end{array}\right]$ (25)
 > L := ["a","b"];
 ${L}{≔}\left[{"a"}{,}{"b"}\right]$ (26)
 > L ||~ 1;
 $\left[{"a1"}{,}{"b1"}\right]$ (27)
 > map(f, [[a,b]]);
 $\left[{\left[{a}{,}{b}\right]}^{{2}}\right]$ (28)
 > map(f~, [[a,b]]);
 $\left[\left[{{a}}^{{2}}{,}{{b}}^{{2}}\right]\right]$ (29)
 > module EC() option object;   local data := <1,2;3,4>;   export ?[]::static := proc(me,idx)        me:-data[op(idx)];   end;   export upperbound::static := proc(me,dim:=NULL)       :-upperbound(me:-data,dim);   end;   local ModulePrint::static := proc( me )       [[me:-data]]   end;   export ModuleCopy := proc( me, proto, d::rtable := NULL )       if d <> NULL then           me:-data := d;       else           me:-data := <7,8;9,10>;       fi;   end;   export getData::static := proc(me)       me:-data;   end;   export setData::static := proc(me, v )       me:-data := v;   end; end;
 $\left[\left[\left[\begin{array}{cc}{1}& {2}\\ {3}& {4}\end{array}\right]\right]\right]$ (30)
 > EC +~ 10;
 $\left[\left[\left[\begin{array}{cc}{11}& {12}\\ {13}& {14}\end{array}\right]\right]\right]$ (31)