Summary: The mo operator element in MathML conveys the meaning of mathematical operation.
The “mo” element displays an operator or other representations, which are treated as an operator in mathematics. The term "operator" also includes fence, separator, accent, comma, semicolon, invisible characters etc. , some of which are used to provide new meaning to the ordinary operator. Hence, “operator” in MathML has wider meaning beyond ordinary operators, consistent with the requirement of growing expanse of mathematical operations.
Many of the important operators contained within “mo” element can be typed directly. They are available on key board; while many others have to be referenced through valid Unicode entity references. The operator symbols, which can be typed from the keyboard include “+”, “-, ”/”, ”*”, ”(“, ”)”, ”{“, ”}”, ”[“, ”]”, “.NOT.”, ”.OR.” etc.
Following example shows the display of operators by "mo" element.
<m:math display="block">
<m:mtable>
<m:mtr>
<m:mtd>
<m:mi>Plus : </m:mi><m:mo>+</m:mo>
<m:mi> ;</m:mi>
<m:mi>Increment : </m:mi><m:mo>++</m:mo>
<m:mi> ;</m:mi>
<m:mi>Logical not : </m:mi><m:mo>.NOT.</m:mo> <m:mi> ;</m:mi>
</m:mtd>
</m:mtr>
<m:mtr>
<m:mtd>
<m:mi>Less than and equal : </m:mi><m:mo> ≤ </m:mo>
<m:mi> ;</m:mi>
<m:mi>Partial operator : </m:mi><m:mo> ∂ </m:mo>
<m:mi> ;</m:mi>
<m:mi>Differentiation : </m:mi><m:mo> ⅆ </m:mo>
<m:mi> ;</m:mi>
<m:mi>Integration : </m:mi><m:mo> ∫ </m:mo>
</m:mtd>
</m:mtr>
</m:mtable>
</m:math>
Save the file after editing as “test.xml”. The display looks like :
In the above example, we have used “mtable” (with “mtr” and “mtd” elements) element for controlling display. See that first three operators in above example have been typed directly from the keyboard; while others have been referenced by entity reference.
MathML design of rendering an operator closely follows mathematical convention. It distinguishes between rendering a character with “mi” element and an operator with “mo” operator in many important ways for notational representation of mathematical expression. Two basic considerations are (i) to manage space around the operator, consistent with the context in which they are displayed and (ii) dimensional change (stretching) of operators in accordance with the dimension of other elements and terms. Space around an operator is managed by “form” attribute, while stretching is managed by “stretchy” attribute of “mo” element. A plus operator ("+") may ,for example, precede or follow an identifier or may lie between two operands. Depending upon its placement, the space around the operator "+" is determined. Similarly, size of a parentheses around an expression must stretch to the height of the expression as in
MathML also allows improvisation of an operator rendered by “mo” element. This generally makes use of other characters rendering elements such as “mi” or "mn" elements in addition to "mo" element and their combination with layout elements like “mfrac” and scripting elements (“msub”, “msup” etc.) Simply put, MathML treats an expression with a “mo” element at core and improvised by other elements - as an operator of class known as “embellished” operator.
Consider encoding for a differentiation operator
"ⅆ"
. This operator when applied to a variable, say t, is represented as
<m:mfrac>
<m:mo> ⅆ </m:mo>
<m:mrow>
<m:mo> ⅆ </m:mo>
<m:mi> x </m:mi>
</m:mrow>
</m:mfrac>
Default values to the attributes of “mo” element are set in accordance with the values contained in “operator dictionary”, which specifies “form”, “fence”, “stretchy”, “lspace” and “rspace” attributes for different operators. The renderer maintains an operator dictionary for most of the operators. W3C recommends a prototype of operator dictionary. These recommendations can be viewed at www.w3.org/TR/MathML2/appendixf.html . If the dictionary does not provide the value for the attribute, then attribute is set with default value as given here:
The "form" attribute specifies whether an operator shall be rendered as "prefix" or "postfix" or "infix" operator. These form types determine space around the operator (left and right of it). Each form type is associated with two attributes ("lspace" and "rspace"), which implements its left space ("lspace") and right space ("rspace"). It is important to understand that form types are basically specification about space around operator and about its role with respect to other elements.
The default value of “form” attribute is set in accordance with three rules, involving "mrow" element. The token elements, including "mo" element, is composed within explicit or inferred "mrow" element. The position of an operator within the "mrow" in horizontal sequence determines the form type of the operator. If operator is the first element, then its form is inferred as "prefix"; if it is in the intermediate position, then its form is inferred as "infix”; and if it is in the end position, then its form is inferred as "postfix". Corresponding to each form, operator library specifies "lspace" and "rspace". It is, however, not necessary that each of the operator has all the three form types. The nature of operator determines the type of forms that a particular operator should be associated with. For example, "+" operator has entries for "prefix" and "infix", but not for "postfix" in the operator dictionary, because "postfix" form of "+" operator is not expected to be placed at the end of an expression.
Now, consider the example of "+" operator appearing twice in an expression in the manner as typed below :
+a + b
The first "+" sign in the above case assumes "prefix" form, while the second "+" sign assumes "infix" form. Once, the form of the operator is determined from the context within "mrow" element, spacing around the operator is determined as specified by "lspace" and "rspace" values given in the operator dictionary. The dictionary suggests following values for these forms of “+” operator :
"+" form="infix" lspace="mediummathspace" rspace="mediummathspace"
"+" form="prefix" lspace="0em" rspace="veryverythinmathspace"
Evidently, "infix" form separates its neighboring elements by "mediummathspace", whereas "prefix" form separates the following element with a very small space specified by "veryverythinmathspace".
Let us now code the example in MathML and see the output :
<m:math display="block">
<m:mrow>
<m:mo> + </m:mo>
<m:mi> a </m:mi>
<m:mo> + </m:mo>
<m:mi> b </m:mi>
</m:mrow>
</m:math>
Save the file after editing as “test.xml”. The display looks like :
As expected first “+” is almost attached to “a”, where as second instance of “+” renders some amount of space around itself. This type of detailing in rendering mathematical expression is vital and critical to maintain highest order of rendering consistencey, which is commensurate with the exact nature of mathematics and the meaning that a mathematical expression conveys. Note that the mark-up paradigm of MathML automatically forces codification in such a manner that no extra effort is required towards maintaining conventions of mathematical display - almost ruling out the possibilities that an expression is displayed in a non-conforming way.
A particular operator does not require to have entries for all the forms in the operator dictionary. Many of the operators in mathematics operate on other entities in forward direction. For example, integration, differentiation, partial differentiation etc. operates on identifiers following it. For this reason, such operators are inherently “prefix” in nature. On the other hand, operators classified as fences are either “prefix” or “postfix” commensurate with their role in mathematical expression. It is very unlikely that a closing bracket “]” is used in the beginning of an expression and as such it has “postfix” form. Dictionary entries for these operators are given here to understand : why there is very small space or no space between these operators and the identifiers on which they operate.
"ⅆ" form="prefix" lspace="0em" rspace="verythinmathspace"
"∂" form="prefix" lspace="0em" rspace="verythinmathspace"
"∫" form="prefix" largeop="true" stretchy="true" lspace="0em"
"(" form="prefix" fence="true" stretchy="true" lspace="0em" rspace="0em"
")" form="postfix" fence="true" stretchy="true" lspace="0em" rspace="0em"
"[" form="prefix" fence="true" stretchy="true" lspace="0em" rspace="0em"
"]" form="postfix" fence="true" stretchy="true" lspace="0em" rspace="0em"
"{" form="prefix" fence="true" stretchy="true" lspace="0em" rspace="0em"
"}" form="postfix" fence="true" stretchy="true" lspace="0em" rspace="0em"
We are at liberty to specify these attributes. It is, however, recommended that we leave the arrangement to the system, which is rendering the mathematical content. It shall ensure consistency in the display, which follows the convention of mathematics as implemented by a particular renderer. The example below demonstrates how we can change the spacing different to default and against the form values as inferred from the context :
<m:math display="block">
<m:mrow>
<m:mo form="infix" rspace="10pt"> + </m:mo>
<m:mi> a </m:mi>
<m:mo form="prefix"> + </m:mo>
<m:mi> b </m:mi>
</m:mrow>
</m:math>
Save the file after editing as “test.xml”. The display lokks like :
Four attributes of “mo” element control stretching of operators. These attributes may assume following values :
Among the operators, the requirement for stretching of fences, arrows, accents (angular cap on identifier) and separators are most profound and visible in mathematical expressions. For this reason, “strechy” attribute of fence and accent operators are set “true” in operator dictionary. Stretching of operators in an expression is restricted by “minsize” and “maxsize” attributes.
The stretchable operators are characterized as predominantly either vertically or horizontally stretchable. The fences, various kinds of vertical arrows (single or double), operators like ∏, ∑, ∫, “/” etc. are set to stretch vertically by default in operator directory.
When stretchable operator and non-stretchable terms are bounded by explicit or inferred “mrow” element, then the stretchable operator grows vertically to cover the non-stretchy term. Consider the example given here :
<m:math display="block">
<m:mrow>
<m:mi> x </m:mi>
<m:mo> = </m:mo>
<m:mo> ( </m:mo>
<m:mfrac>
<m:mi>a</m:mi>
<m:mi>b</m:mi>
</m:mfrac>
<m:mo> ) </m:mo>
</m:mrow>
</m:math>
Save the file after editing as “test.xml”. The display looks like :
We can, however, control the growth of parenthese by setting “maxsize” attribute to 1 i.e. equal to its normal size.
<m:math display="block">
<m:mrow>
<m:mi> x </m:mi>
<m:mo> = </m:mo>
<m:mo maxsize="1"> ( </m:mo>
<m:mfrac>
<m:mi>a</m:mi>
<m:mi>b</m:mi>
</m:mfrac>
<m:mo maxsize="1"> ) </m:mo>
</m:mrow>
</m:math>
Save the file after editing as “test.xml”. The display looks like :
Thus, setting "maxsize" attribute overrides the default behavior, which allows the parentheses to strech and cover the non-stretchy expression. Let us, now experiment with other than fence character like ∑ and observe their behavior with other terms :
<m:math display="block">
<m:mrow>
<m:mo> ∑ </m:mo>
<m:mo> ( </m:mo>
<m:mfrac>
<m:mi>A</m:mi>
<m:mi>B</m:mi>
</m:mfrac>
<m:mo> ) </m:mo>
</m:mrow>
</m:math>
Save the file after editing as “test.xml”. The display looks like :
Control for stretching can be selective as well. For example, we can set stretchy=”false” on the opening parenthesis to restrict it to grow.
<m:math display="block">
<m:mrow>
<m:mi> x </m:mi>
<m:mo> = </m:mo>
<m:mo stretchy="false"> ( </m:mo>
<m:mfrac>
<m:mi>a</m:mi>
<m:mi>b</m:mi>
</m:mfrac>
<m:mo> ) </m:mo>
</m:mrow>
</m:math>
Save the file after editing as “test.xml”. The display looks like :
In situation where, the expression bounded by “mrow” tags contains terms of different heights, the stretchable parentheses grow to cover the highest of the terms.
<m:math display="block">
<m:mrow>
<m:mi> x </m:mi>
<m:mo> = </m:mo>
<m:mo> ( </m:mo>
<m:mfrac>
<m:mi>a</m:mi>
<m:mi>b</m:mi>
</m:mfrac>
<m:mo> + </m:mo>
<m:mfrac>
<m:mrow>
<m:mfrac>
<m:mi>c</m:mi>
<m:mi>d</m:mi>
</m:mfrac>
</m:mrow>
<m:mi>e</m:mi>
</m:mfrac>
<m:mo> ) </m:mo>
</m:mrow>
</m:math>
Save the file after editing as “test.xml”. The display lokks like :
The symmetric attribute is designed to stretch operator in both vertical and horizontal direction from the axis of the characters in equal magnitude. The symmetric attribute applies only to characters, which can stretch vertically; otherwise this attribute is ignored. Usually, this attribute is set “true” for vertically stretchable operator, but in certain cases involving matrix of unequal size, we may prefer to set it “false” as demonstrated in the example here :
<m:math display="block">
<m:mrow>
<m:mi> x </m:mi>
<m:mo> = </m:mo>
<m:mo symmetric="false"> ( </m:mo>
<m:mtable align="bottom">
<m:mtr>
<m:mtd>
<m:mi>a</m:mi>
</m:mtd>
<m:mtd>
<m:mi>b</m:mi>
</m:mtd>
</m:mtr>
<m:mtr>
<m:mtd>
<m:mn>d</m:mn>
</m:mtd>
<m:mtd>
<m:mn>e</m:mn>
</m:mtd>
</m:mtr>
</m:mtable>
<m:mo symmetric="false"> ) </m:mo>
<m:mo symmetric="false"> ( </m:mo>
<m:mtable align="bottom">
<m:mtr>
<m:mtd>
<m:mi>a</m:mi>
</m:mtd>
<m:mtd>
<m:mi>b</m:mi>
</m:mtd>
</m:mtr>
<m:mtr>
<m:mtd>
<m:mn>d</m:mn>
</m:mtd>
<m:mtd>
<m:mn>e</m:mn>
</m:mtd>
</m:mtr>
<m:mtr>
<m:mtd>
<m:mn>d</m:mn>
</m:mtd>
<m:mtd>
<m:mn>e</m:mn>
</m:mtd>
</m:mtr>
</m:mtable>
<m:mo symmetric="false"> ) </m:mo>
</m:mrow>
</m:math>
Save the file after editing as “test.xml”. The display lokks like :
Matrix operation of unequal sizes uses notation which is aligned to base. This type of controlling stretching in specific direction is, therefore, extremely useful in such situations.
In case, the “mrow” domain contains non-stretchable terms of normal height and other stretchable terms, then all the terms, including the fence operator grows to the maximum normal height.
<m:math display="block">
<m:mrow>
<m:mi> x </m:mi>
<m:mo> = </m:mo>
<m:mo> ( </m:mo>
<m:mo> ∫ </m:mo>
<m:mi> f</m:mi>
<m:mo> ( </m:mo>
<m:mi> x </m:mi>
<m:mo> ) </m:mo>
<m:mi> ⅆ </m:mi>
<m:mi> x </m:mi>
<m:mo> ) </m:mo>
</m:mrow>
</m:math>
Save the file after editing as “test.xml”. The display lokks like :
As against fence operator, the accent and horizontal arrows are stretchable in horizontal direction by default. The growth, in this case, is controlled by “munder”, “mover” and “munderover” elements, which contain the operator. The “munder”, “mover” and “munderover” elements, as the names suggest, allow drawing of an operator "under" or "over" or both about a character(s) or expresison. The scripting elements takes a base argument about which the operator is to be drawn and one (“munder” and “mover”) operator or two (“munderover”) operators for being placed about the base. We shall see that the operator grows horizontally to cover the other element.
<m:math display="block">
<m:mi> A </m:mi>
<m:munderover>
<m:mo> → </m:mo>
<m:mtext> 50 degree C </m:mtext>
<m:mtext> 200 psi </m:mtext>
</m:munderover>
<m:mi> B </m:mi>
</m:math>
Save the file after editing as “test.xml”. The display looks like :
These attributes may assume following values :
All these attributes accept boolean values “true” or “false”. The attribute “fence” is designed for non-visual rendering like audio rendering. As such, this attribute has no impact on the visual aspect of rendering. The role of “separator” attribute is also not significant and may be left to default value.
The “largeop” attribute determines the size of the operator. If it is true, then the operator is drawn larger than its normal size. For example, ∫ and ∏ operators are displayed as large operator as “largeop” attribute for these operators are set “true” by default. If we need to display the normal size, then their "largeop" attribute is set to "false".
<m:math display="block">
<m:mrow>
<m:mo> ∏ </m:mo>
<m:mo> , </m:mo>
<m:mo> ∫ </m:mo>
<m:mo> , </m:mo>
<m:mo largeop="false"> ∏ </m:mo>
<m:mo> , </m:mo>
<m:mo largeop="false"> ∫ </m:mo>
</m:mrow>
</m:math>
Save the file after editing as “test.xml”. The display looks like :
The movablelimits attribute allows underscripts and overscripts to be represented as subscript and superscript respectively. This rendering of under and over scripts as sub and super scripts is possible by seting this attribute to true. The implementation of this attribute by renderers is not yet consistent.
<m:math display="block">
<m:munderover>
<m:mo movablelimits='true'> ∑ </m:mo>
<m:mi> a </m:mi>
<m:mi> b </m:mi>
</m:munderover>
<m:munderover>
<m:mo movablelimits='false'> ∑ </m:mo>
<m:mi> a </m:mi>
<m:mi> b </m:mi>
</m:munderover>
</m:math>
Save the file after editing as “test.xml”. The display looks like :
The accent attribute determines whether an operator is treated as accent (diacritical mark) when used as an underscript or overscript.