diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index beae3c047..57eee3d90 100755
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -49,5 +49,5 @@ jobs:
pip install pyocr # from full
pip install -e .[dev]
make pytest gstest
- make doctest
+ make doctest DOCTEST_OPTIONS="--exclude WordCloud"
# make check
diff --git a/mathics/builtin/atomic/numbers.py b/mathics/builtin/atomic/numbers.py
index 93b6c6807..ca1b0ed34 100644
--- a/mathics/builtin/atomic/numbers.py
+++ b/mathics/builtin/atomic/numbers.py
@@ -771,7 +771,7 @@ class Precision(Builtin):
Note that the result could be slightly different than the obtained \
- in WMA, due to differencs in the internal representation of the real numbers.
+ in WMA, due to differences in the internal representation of the real numbers.
The precision of an exact number, e.g. an Integer, is 'Infinity':
@@ -792,25 +792,22 @@ class Precision(Builtin):
>> Precision[0.5]
= MachinePrecision
- In compound expressions, the 'Precision' is fixed by the number with
+ In compound expressions, the 'Precision' is fixed by the number with \
the lowest 'Precision':
>> Precision[{{1, 1.`},{1.`5, 1.`10}}]
= 5.
- For non-zero Real values, it holds in general:
-
- 'Accuracy'[$z$] == 'Precision'[$z$] + 'Log'[$z$]
+ In general, 'Accuracy'[$z$] == 'Precision'[$z$] + 'Log'[$z$] \
+ for non-zero Real values:
>> (Accuracy[z] == Precision[z] + Log[z])/.z-> 37.`
= True
- The case of `0.` values is special. Following WMA, in a Machine Real\
- representation, the precision is set to 'MachinePrecision':
+ Following WMA, values in Machine Real representation starting with '0.' are values are special:
>> Precision[0.]
= MachinePrecision
- On the other hand, for a Precision Real with fixed accuracy,\
- the precision is evaluated to 0.:
+ On the other hand, for a Precision Real with fixed accuracy, the precision is evaluated to '0.':
>> Precision[0.``3]
= 0.
diff --git a/mathics/builtin/atomic/symbols.py b/mathics/builtin/atomic/symbols.py
index 7c190e53f..501432983 100644
--- a/mathics/builtin/atomic/symbols.py
+++ b/mathics/builtin/atomic/symbols.py
@@ -416,6 +416,7 @@ class Information(PrefixOperator):
'Information[$symbol$]'
Prints information about a $symbol$
+
'Information' does not print information for 'ReadProtected' symbols.
'Information' uses 'InputForm' to format values.
diff --git a/mathics/builtin/exp_structure/general.py b/mathics/builtin/exp_structure/general.py
index f18663edd..8c973b3a8 100644
--- a/mathics/builtin/exp_structure/general.py
+++ b/mathics/builtin/exp_structure/general.py
@@ -1,21 +1,18 @@
# -*- coding: utf-8 -*-
"""
-General Structural Expression Functions
+Structural Expression Functions
"""
-from mathics.core.atoms import Integer, Integer0, Integer1, Rational
+from mathics.core.atoms import Integer
from mathics.core.builtin import BinaryOperator, Builtin, Predefined
from mathics.core.exceptions import InvalidLevelspecError
from mathics.core.expression import Evaluation, Expression
from mathics.core.list import ListExpression
from mathics.core.rules import Pattern
-from mathics.core.symbols import Atom, Symbol, SymbolFalse, SymbolTrue
+from mathics.core.symbols import Atom, SymbolFalse, SymbolTrue
from mathics.core.systemsymbols import SymbolMap
from mathics.eval.parts import python_levelspec, walk_levels
-SymbolOperate = Symbol("Operate")
-SymbolSortBy = Symbol("SortBy")
-
class ApplyLevel(BinaryOperator):
"""
@@ -45,116 +42,6 @@ class ApplyLevel(BinaryOperator):
summary_text = "apply a function to a list, at the top level"
-class BinarySearch(Builtin):
- """
-
- :Binary search algorithm:
- https://en.wikipedia.org/wiki/Binary_search_algorithm (
- :WMA:
- https://reference.wolfram.com/language/ref/BinarySearch.html)
-
-
- - 'CombinatoricaOld`BinarySearch[$l$, $k$]'
-
- searches the list $l$, which has to be sorted, for key $k$ and \
- returns its index in $l$.
-
- If $k$ does not exist in $l$, 'BinarySearch' returns ($a$ + $b$) / 2, \
- where $a$ and $b$ are the indices between which $k$ would have \
- to be inserted in order to maintain the sorting order in $l$.
-
- Please note that $k$ and the elements in $l$ need to be comparable \
- under a
- :strict total order:
- https://en.wikipedia.org/wiki/Total_order.
-
-
- 'CombinatoricaOld`BinarySearch[$l$, $k$, $f$]'
-
- gives the index of $k$ in the elements of $l$ if $f$ is applied to the \
- latter prior to comparison. Note that $f$ \
- needs to yield a sorted sequence if applied to the elements of $l$.
-
-
- Number 100 is found at exactly in the fourth place of the given list:
-
- >> CombinatoricaOld`BinarySearch[{3, 4, 10, 100, 123}, 100]
- = 4
-
- Number 7 is found in between the second and third place (3, and 9)\
- of the given list. The numerical difference between 3 and 9 does \
- not figure into the .5 part of 2.5:
-
- >> CombinatoricaOld`BinarySearch[{2, 3, 9}, 7] // N
- = 2.5
-
- 0.5 is what you get when the item comes before the given list:
-
- >> CombinatoricaOld`BinarySearch[{-10, 5, 8, 10}, -100] // N
- = 0.5
-
- And here is what you see when the item comes at the end of the list:
-
- >> CombinatoricaOld`BinarySearch[{-10, 5, 8, 10}, 20] // N
- = 4.5
-
- >> CombinatoricaOld`BinarySearch[{{a, 1}, {b, 7}}, 7, #[[2]]&]
- = 2
- """
-
- context = "CombinatoricaOld`"
-
- rules = {
- "CombinatoricaOld`BinarySearch[li_List, k_] /; Length[li] > 0": "CombinatoricaOld`BinarySearch[li, k, Identity]"
- }
-
- summary_text = "search a sorted list for a key"
-
- def eval(self, li, k, f, evaluation: Evaluation):
- "CombinatoricaOld`BinarySearch[li_List, k_, f_] /; Length[li] > 0"
-
- elements = li.elements
-
- lower_index = 1
- upper_index = len(elements)
-
- if (
- lower_index > upper_index
- ): # empty list li? Length[l] > 0 condition should guard us, but check anyway
- return Symbol("$Aborted")
-
- # "transform" is a handy wrapper for applying "f" or nothing
- if f.get_name() == "System`Identity":
-
- def transform(x):
- return x
-
- else:
-
- def transform(x):
- return Expression(f, x).evaluate(evaluation)
-
- # loop invariants (true at any time in the following loop):
- # (1) lower_index <= upper_index
- # (2) k > elements[i] for all i < lower_index
- # (3) k < elements[i] for all i > upper_index
- while True:
- pivot_index = (lower_index + upper_index) >> 1 # i.e. a + (b - a) // 2
- # as lower_index <= upper_index, lower_index <= pivot_index <= upper_index
- pivot = transform(elements[pivot_index - 1]) # 1-based to 0-based
-
- # we assume a trichotomous relation: k < pivot, or k = pivot, or k > pivot
- if k < pivot:
- if pivot_index == lower_index: # see invariant (2), to see that
- # k < elements[pivot_index] and k > elements[pivot_index - 1]
- return Rational((pivot_index - 1) + pivot_index, 2)
- upper_index = pivot_index - 1
- elif k == pivot:
- return Integer(pivot_index)
- else: # k > pivot
- if pivot_index == upper_index: # see invariant (3), to see that
- # k > elements[pivot_index] and k < elements[pivot_index + 1]
- return Rational(pivot_index + (pivot_index + 1), 2)
- lower_index = pivot_index + 1
-
-
class Depth(Builtin):
"""
:WMA link:https://reference.wolfram.com/language/ref/Depth.html
@@ -340,171 +227,6 @@ class Null(Predefined):
summary_text = "implicit result for expressions that do not yield a result"
-class Operate(Builtin):
- """
-
- :WMA link:
- https://reference.wolfram.com/language/ref/Operate.html
-
-
- - 'Operate[$p$, $expr$]'
-
- applies $p$ to the head of $expr$.
-
-
- 'Operate[$p$, $expr$, $n$]'
-
- applies $p$ to the $n$th head of $expr$.
-
-
- >> Operate[p, f[a, b]]
- = p[f][a, b]
-
- The default value of $n$ is 1:
- >> Operate[p, f[a, b], 1]
- = p[f][a, b]
-
- With $n$=0, 'Operate' acts like 'Apply':
- >> Operate[p, f[a][b][c], 0]
- = p[f[a][b][c]]
- """
-
- summary_text = "apply a function to the head of an expression"
- messages = {
- "intnn": "Non-negative integer expected at position `2` in `1`.",
- }
-
- def eval(self, p, expr, n, evaluation: Evaluation):
- "Operate[p_, expr_, Optional[n_, 1]]"
-
- head_depth = n.get_int_value()
- if head_depth is None or head_depth < 0:
- evaluation.message(
- "Operate", "intnn", Expression(SymbolOperate, p, expr, n), 3
- )
- return
-
- if head_depth == 0:
- # Act like Apply
- return Expression(p, expr)
-
- if isinstance(expr, Atom):
- return expr
-
- expr = expr.copy()
- e = expr
-
- for i in range(1, head_depth):
- e = e.head
- if isinstance(e, Atom):
- # n is higher than the depth of heads in expr: return
- # expr unmodified.
- return expr
-
- # Otherwise, if we get here, e.head points to the head we need
- # to apply p to. Python's reference semantics mean that this
- # assignment modifies expr as well.
- e.set_head(Expression(p, e.head))
-
- return expr
-
-
-class Order(Builtin):
- """
- :WMA link:https://reference.wolfram.com/language/ref/Order.html
-
-
- - 'Order[$x$, $y$]'
-
- returns a number indicating the canonical ordering of $x$ and $y$. \
- 1 indicates that $x$ is before $y$, and -1 that $y$ is before $x$. \
- 0 indicates that there is no specific ordering. Uses the same order \
- as 'Sort'.
-
-
- >> Order[7, 11]
- = 1
-
- >> Order[100, 10]
- = -1
-
- >> Order[x, z]
- = 1
-
- >> Order[x, x]
- = 0
- """
-
- summary_text = "order expressions"
-
- def eval(self, x, y, evaluation: Evaluation):
- "Order[x_, y_]"
- if x < y:
- return Integer1
- elif x > y:
- return Integer(-1)
- else:
- return Integer0
-
-
-class OrderedQ(Builtin):
- """
-
- :WMA link:
- https://reference.wolfram.com/language/ref/OrderedQ.html
-
-
- - 'OrderedQ[{$a$, $b$}]'
-
- is 'True' if $a$ sorts before $b$ according to canonical
- ordering.
-
-
- >> OrderedQ[{a, b}]
- = True
- >> OrderedQ[{b, a}]
- = False
- """
-
- summary_text = "test whether elements are canonically sorted"
-
- def eval(self, expr, evaluation: Evaluation):
- "OrderedQ[expr_]"
-
- for index, value in enumerate(expr.elements[:-1]):
- if expr.elements[index] <= expr.elements[index + 1]:
- continue
- else:
- return SymbolFalse
- return SymbolTrue
-
-
-class PatternsOrderedQ(Builtin):
- """
-
- :WMA link:
- https://reference.wolfram.com/language/ref/PatternsOrderedQ.html
-
-
- - 'PatternsOrderedQ[$patt1$, $patt2$]'
-
- returns 'True' if pattern $patt1$ would be applied before
- $patt2$ according to canonical pattern ordering.
-
-
- >> PatternsOrderedQ[x__, x_]
- = False
- >> PatternsOrderedQ[x_, x__]
- = True
- >> PatternsOrderedQ[b, a]
- = True
- """
-
- summary_text = "test whether patterns are canonically sorted"
-
- def eval(self, p1, p2, evaluation: Evaluation):
- "PatternsOrderedQ[p1_, p2_]"
-
- if p1.get_sort_key(True) <= p2.get_sort_key(True):
- return SymbolTrue
- else:
- return SymbolFalse
-
-
class SortBy(Builtin):
"""
@@ -584,31 +306,3 @@ def __gt__(self, other):
new_indices = sorted(list(range(len(raw_keys))), key=Key)
new_elements = [raw_keys[i] for i in new_indices] # reorder elements
return li.restructure(li.head, new_elements, evaluation)
-
-
-class Through(Builtin):
- """
-
- :WMA link:
- https://reference.wolfram.com/language/ref/Through.html
-
-
- - 'Through[$p$[$f$][$x$]]'
-
- gives $p$[$f$[$x$]].
-
-
- >> Through[f[g][x]]
- = f[g[x]]
- >> Through[p[f, g][x]]
- = p[f[x], g[x]]
- """
-
- summary_text = "distribute operators that appears inside the head of expressions"
-
- def eval(self, p, args, x, evaluation: Evaluation):
- "Through[p_[args___][x___]]"
-
- elements = []
- for element in args.get_sequence():
- elements.append(Expression(element, *x.get_sequence()))
- return Expression(p, *elements)
diff --git a/mathics/builtin/exp_structure/head_related.py b/mathics/builtin/exp_structure/head_related.py
new file mode 100644
index 000000000..740da2725
--- /dev/null
+++ b/mathics/builtin/exp_structure/head_related.py
@@ -0,0 +1,102 @@
+"""
+Head-Related Operations
+"""
+
+from mathics.core.builtin import Builtin
+from mathics.core.expression import Evaluation, Expression
+from mathics.core.symbols import Atom
+from mathics.core.systemsymbols import SymbolOperate
+
+
+class Operate(Builtin):
+ """
+
+ :WMA link:
+ https://reference.wolfram.com/language/ref/Operate.html
+
+
+ - 'Operate[$p$, $expr$]'
+
- applies $p$ to the head of $expr$.
+
+
- 'Operate[$p$, $expr$, $n$]'
+
- applies $p$ to the $n$th head of $expr$.
+
+
+ >> Operate[p, f[a, b]]
+ = p[f][a, b]
+
+ The default value of $n$ is 1:
+ >> Operate[p, f[a, b], 1]
+ = p[f][a, b]
+
+ With $n$=0, 'Operate' acts like 'Apply':
+ >> Operate[p, f[a][b][c], 0]
+ = p[f[a][b][c]]
+ """
+
+ summary_text = "apply a function to the head of an expression"
+ messages = {
+ "intnn": "Non-negative integer expected at position `2` in `1`.",
+ }
+
+ def eval(self, p, expr, n, evaluation: Evaluation):
+ "Operate[p_, expr_, Optional[n_, 1]]"
+
+ head_depth = n.get_int_value()
+ if head_depth is None or head_depth < 0:
+ evaluation.message(
+ "Operate", "intnn", Expression(SymbolOperate, p, expr, n), 3
+ )
+ return
+
+ if head_depth == 0:
+ # Act like Apply
+ return Expression(p, expr)
+
+ if isinstance(expr, Atom):
+ return expr
+
+ expr = expr.copy()
+ e = expr
+
+ for i in range(1, head_depth):
+ e = e.head
+ if isinstance(e, Atom):
+ # n is higher than the depth of heads in expr: return
+ # expr unmodified.
+ return expr
+
+ # Otherwise, if we get here, e.head points to the head we need
+ # to apply p to. Python's reference semantics mean that this
+ # assignment modifies expr as well.
+ e.set_head(Expression(p, e.head))
+
+ return expr
+
+
+class Through(Builtin):
+ """
+
+ :WMA link:
+ https://reference.wolfram.com/language/ref/Through.html
+
+
+ - 'Through[$p$[$f$][$x$]]'
+
- gives $p$[$f$[$x$]].
+
+
+ >> Through[f[g][x]]
+ = f[g[x]]
+ >> Through[p[f, g][x]]
+ = p[f[x], g[x]]
+ """
+
+ summary_text = "distribute operators that appears inside the head of expressions"
+
+ def eval(self, p, args, x, evaluation: Evaluation):
+ "Through[p_[args___][x___]]"
+
+ elements = []
+ for element in args.get_sequence():
+ elements.append(Expression(element, *x.get_sequence()))
+ return Expression(p, *elements)
diff --git a/mathics/builtin/exp_structure/size_and_sig.py b/mathics/builtin/exp_structure/size_and_sig.py
index e54bc37a7..20af4f1c2 100644
--- a/mathics/builtin/exp_structure/size_and_sig.py
+++ b/mathics/builtin/exp_structure/size_and_sig.py
@@ -78,20 +78,20 @@ class Hash(Builtin):
Returns the hash in the specified format.
- > Hash["The Adventures of Huckleberry Finn"]
+ >> Hash["The Adventures of Huckleberry Finn"]
= 213425047836523694663619736686226550816
- > Hash["The Adventures of Huckleberry Finn", "SHA256"]
+ >> Hash["The Adventures of Huckleberry Finn", "SHA256"]
= 95092649594590384288057183408609254918934351811669818342876362244564858646638
- > Hash[1/3]
+ >> Hash[1/3]
= 56073172797010645108327809727054836008
- > Hash[{a, b, {c, {d, e, f}}}]
+ >> Hash[{a, b, {c, {d, e, f}}}]
= 135682164776235407777080772547528225284
- > Hash[SomeHead[3.1415]]
- = 58042316473471877315442015469706095084
+ >> Hash[SomeHead[3.1415]]
+ = 47205238268993602951487675588386522878
>> Hash[{a, b, c}, "xyzstr"]
= Hash[{a, b, c}, xyzstr, Integer]
diff --git a/mathics/builtin/graphics.py b/mathics/builtin/graphics.py
index eee38b9b0..2af729e66 100644
--- a/mathics/builtin/graphics.py
+++ b/mathics/builtin/graphics.py
@@ -485,7 +485,9 @@ class PointSize(_Size):
'PointSize[$t$]'
sets the diameter of points to $t$, which is relative to the overall width.
- 'PointSize' can be used for both two- and three-dimensional graphics. The initial default pointsize is 0.008 for two-dimensional graphics and 0.01 for three-dimensional graphics.
+
+ 'PointSize' can be used for both two- and three-dimensional graphics. \
+ The initial default pointsize is 0.008 for two-dimensional graphics and 0.01 for three-dimensional graphics.
>> Table[Graphics[{PointSize[r], Point[{0, 0}]}], {r, {0.02, 0.05, 0.1, 0.3}}]
= {-Graphics-, -Graphics-, -Graphics-, -Graphics-}
diff --git a/mathics/builtin/intfns/combinatorial.py b/mathics/builtin/intfns/combinatorial.py
index 8c1edafef..cc1a30989 100644
--- a/mathics/builtin/intfns/combinatorial.py
+++ b/mathics/builtin/intfns/combinatorial.py
@@ -355,8 +355,9 @@ def _compute(self, n, c_ff, c_ft, c_tf, c_tt):
class Subsets(Builtin):
"""
- :WMA link:
- https://reference.wolfram.com/language/ref/Subsets.html
+ :Subset:
+ https://en.wikipedia.org/wiki/Subset (:WMA link:
+ https://reference.wolfram.com/language/ref/Subsets.html)
- 'Subsets[$list$]'
@@ -396,8 +397,8 @@ class Subsets(Builtin):
= {{a, b, c}, {a, b, d}, {a, b, e}, {a, c, d}, {a, c, e}}
All subsets with even length:
- >> Subsets[{a, b, c, d, e}, {0, 5, 2}]
- = {{}, {a, b}, {a, c}, {a, d}, {a, e}, {b, c}, {b, d}, {b, e}, {c, d}, {c, e}, {d, e}, {a, b, c, d}, {a, b, c, e}, {a, b, d, e}, {a, c, d, e}, {b, c, d, e}}
+ >> Subsets[{a, b, c, d}, {0, 4, 2}]
+ = {{}, {a, b}, {a, c}, {a, d}, {b, c}, {b, d}, {c, d}, {a, b, c, d}}
The 25th subset:
>> Subsets[Range[5], All, {25}]
diff --git a/mathics/builtin/numbers/constants.py b/mathics/builtin/numbers/constants.py
index 119f94330..4eb1e6a6b 100644
--- a/mathics/builtin/numbers/constants.py
+++ b/mathics/builtin/numbers/constants.py
@@ -272,6 +272,10 @@ class ComplexInfinity(_SympyConstant):
ComplexInfinity though is a special case of DirectedInfinity:
>> FullForm[ComplexInfinity]
= DirectedInfinity[]
+
+ See also
+ :'DirectedInfinity':
+ /doc/reference-of-built-in-symbols/mathematical-functions/directedinfinity/.
"""
summary_text = "infinite complex quantity of undetermined direction"
@@ -493,14 +497,31 @@ class Infinity(_SympyConstant):
- a symbol that represents an infinite real quantity.
+ 'Infinity' sometimes appears as the result of a calculation:
+ >> Precision[1]
+ = Infinity
+
+ But 'Infinity' it often used as a value in expressions:
>> 1 / Infinity
= 0
+
>> Infinity + 100
= Infinity
- Use 'Infinity' in sum and limit calculations:
+ 'Infinity' often appears in sum and limit calculations:
>> Sum[1/x^2, {x, 1, Infinity}]
= Pi ^ 2 / 6
+
+ >> Limit[1/x, x->0]
+ = -Infinity
+
+ However, 'Infinity' a shorthand for 'DirectedInfinity[1]':
+ >> FullForm[Infinity]
+ = DirectedInfinity[1]
+
+ See also
+ :'DirectedInfinity':
+ /doc/reference-of-built-in-symbols/mathematical-functions/directedinfinity/.
"""
sympy_name = "oo"
diff --git a/mathics/builtin/numeric.py b/mathics/builtin/numeric.py
index 73d625284..613a1a03a 100644
--- a/mathics/builtin/numeric.py
+++ b/mathics/builtin/numeric.py
@@ -185,6 +185,7 @@ class N(Builtin):
= 0.14286
You can manually assign numerical values to symbols.
+
When you do not specify a precision, 'MachinePrecision' is taken.
>> N[a] = 10.9
= 10.9
diff --git a/mathics/builtin/statistics/orderstats.py b/mathics/builtin/statistics/orderstats.py
index 56257a784..ebe750d50 100644
--- a/mathics/builtin/statistics/orderstats.py
+++ b/mathics/builtin/statistics/orderstats.py
@@ -35,7 +35,7 @@ class Quantile(Builtin):
:Quantile:
https://en.wikipedia.org/wiki/Quantile (
- :WMA:
+ :WMA link:
https://reference.wolfram.com/language/ref/Quantile.html)
In statistics and probability, quantiles are cut points dividing the \
@@ -50,12 +50,14 @@ class Quantile(Builtin):
'Quantile[$list$, $q$, {{$a$,$b$}, {$c$,$d$}}]'
uses the quantile definition specified by parameters $a$, $b$, $c$, $d$.
- For a list of length $n$, 'Quantile[list, $q$, {{$a$,$b$}, {$c$,$d$}}]' depends on $x$=$a$+($n$+$b$)$q$.
+ For a list of length $n$:
+ 'Quantile[$list$, $q$, {{$a$,$b$}, {$c$,$d$}}]'
+ depends on $x$=$a$+($n$+$b$)$q$.
If $x$ is an integer, the result is '$s$[[$x$]]', where $s$='Sort[list,Less]'.
- Otherwise, the result is \
- 's[[Floor[x]]]+(s[[Ceiling[x]]]-s[[Floor[x]]])(c+dFractionalPart[x])', \
+ Otherwise, the result is:
+ 's[[Floor[x]]]+(s[[Ceiling[x]]]-s[[Floor[x]]])(c+dFractionalPart[x])',
with the indices taken to be 1 or n if they are out of range.
The default choice of parameters is '{{0,0},{1,0}}'.
@@ -157,7 +159,7 @@ class Quartiles(Builtin):
"""
:Quartile:
https://en.wikipedia.org/wiki/Quartile (
- :WMA:
+ :WMA link:
https://reference.wolfram.com/language/ref/Quartiles.html)
- 'Quartiles[$list$]'
diff --git a/mathics/builtin/testing_expressions/expression_tests.py b/mathics/builtin/testing_expressions/expression_tests.py
index 59ce5547b..5b32b386b 100644
--- a/mathics/builtin/testing_expressions/expression_tests.py
+++ b/mathics/builtin/testing_expressions/expression_tests.py
@@ -1,6 +1,7 @@
"""
Expression Tests
"""
+from mathics.core.atoms import Integer0, Integer1, IntegerM1
from mathics.core.builtin import Builtin, PatternError, Test
from mathics.core.evaluation import Evaluation
from mathics.core.symbols import SymbolFalse, SymbolTrue
@@ -67,3 +68,99 @@ def eval(self, expr, form, evaluation: Evaluation):
except PatternError as e:
evaluation.message(e.name, e.tag, *(e.args))
return SymbolFalse
+
+
+class Order(Builtin):
+ """
+ :WMA link:https://reference.wolfram.com/language/ref/Order.html
+
+
+ - 'Order[$x$, $y$]'
+
- returns a number indicating the canonical ordering of $x$ and $y$. \
+ 1 indicates that $x$ is before $y$, and -1 that $y$ is before $x$. \
+ 0 indicates that there is no specific ordering. Uses the same order \
+ as 'Sort'.
+
+
+ >> Order[7, 11]
+ = 1
+
+ >> Order[100, 10]
+ = -1
+
+ >> Order[x, z]
+ = 1
+
+ >> Order[x, x]
+ = 0
+ """
+
+ summary_text = "order expressions"
+
+ def eval(self, x, y, evaluation: Evaluation):
+ "Order[x_, y_]"
+ if x < y:
+ return Integer1
+ elif x > y:
+ return IntegerM1
+ else:
+ return Integer0
+
+
+class OrderedQ(Builtin):
+ """
+
+ :WMA link:
+ https://reference.wolfram.com/language/ref/OrderedQ.html
+
+
+ - 'OrderedQ[{$a$, $b$}]'
+
- is 'True' if $a$ sorts before $b$ according to canonical
+ ordering.
+
+
+ >> OrderedQ[{a, b}]
+ = True
+ >> OrderedQ[{b, a}]
+ = False
+ """
+
+ summary_text = "test whether elements are canonically sorted"
+
+ def eval(self, expr, evaluation: Evaluation):
+ "OrderedQ[expr_]"
+
+ for index, value in enumerate(expr.elements[:-1]):
+ if expr.elements[index] <= expr.elements[index + 1]:
+ continue
+ else:
+ return SymbolFalse
+ return SymbolTrue
+
+
+# Note not in WMA anymore
+class PatternsOrderedQ(Builtin):
+ """
+
+ - 'PatternsOrderedQ[$patt1$, $patt2$]'
+
- returns 'True' if pattern $patt1$ would be applied before
+ $patt2$ according to canonical pattern ordering.
+
+
+ >> PatternsOrderedQ[x__, x_]
+ = False
+ >> PatternsOrderedQ[x_, x__]
+ = True
+ >> PatternsOrderedQ[b, a]
+ = True
+ """
+
+ summary_text = "test whether patterns are canonically sorted"
+
+ def eval(self, p1, p2, evaluation: Evaluation):
+ "PatternsOrderedQ[p1_, p2_]"
+
+ if p1.get_sort_key(True) <= p2.get_sort_key(True):
+ return SymbolTrue
+ else:
+ return SymbolFalse
diff --git a/mathics/core/systemsymbols.py b/mathics/core/systemsymbols.py
index 8ce706595..55bb40960 100644
--- a/mathics/core/systemsymbols.py
+++ b/mathics/core/systemsymbols.py
@@ -172,6 +172,7 @@
SymbolNumericQ = Symbol("System`NumericQ")
SymbolO = Symbol("System`O")
SymbolOpacity = Symbol("System`Opacity")
+SymbolOperate = Symbol("System`Operate")
SymbolOptionValue = Symbol("System`OptionValue")
SymbolOptional = Symbol("System`Optional")
SymbolOptions = Symbol("System`Options")
@@ -229,6 +230,7 @@
SymbolSin = Symbol("System`Sin")
SymbolSinh = Symbol("System`Sinh")
SymbolSlot = Symbol("System`Slot")
+SymbolSortBy = Symbol("System`SortBy")
SymbolSparseArray = Symbol("System`SparseArray")
SymbolSplit = Symbol("System`Split")
SymbolSqrt = Symbol("System`Sqrt")
diff --git a/mathics/doc/documentation/1-Manual.mdoc b/mathics/doc/documentation/1-Manual.mdoc
index f878f2660..cf98a811f 100644
--- a/mathics/doc/documentation/1-Manual.mdoc
+++ b/mathics/doc/documentation/1-Manual.mdoc
@@ -1,8 +1,7 @@
-\Mathics---to be pronounced like "Mathematics" without the "emat"---is
-a :computer algebra
+\Mathics is a :computer algebra
system:https://en.wikipedia.org/wiki/Computer_algebra_system. It
is a free, open-source alternative to \Mathematica or the \Wolfram
Language. However, \Mathics builds around and on top of the Python
diff --git a/mathics/doc/latex/mathics.tex b/mathics/doc/latex/mathics.tex
index 0462a6bc1..665bdd966 100644
--- a/mathics/doc/latex/mathics.tex
+++ b/mathics/doc/latex/mathics.tex
@@ -21,6 +21,16 @@
\documentclass[index=totoc,fleqn,10pt,oneside,toc=flat]{scrbook}
+% The number is sections and subsections can get high, for example:
+% 26.2.16 PolarPlot
+% ^^^^^^^
+% So we need the below to automatically calculate the width numbers can take
+% See:
+% https://tex.stackexchange.com/questions/694088/koma-book-class-listoftables-increase-the-space-between-the-number-and-title-of
+\DeclareTOCStyleEntry[dynnumwidth]{default}{chapter}
+\DeclareTOCStyleEntry[dynnumwidth]{default}{section}
+\DeclareTOCStyleEntry[dynnumwidth]{default}{subsection}
+
%\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{gensymb} % For \degree. usepackage needs to be early.
@@ -31,8 +41,13 @@
\usepackage{asymptote}
\usepackage[hypertexnames=false]{hyperref} % make hyperref aware of chapter reset for built-in symbols
% (http://tex.stackexchange.com/questions/6098/wrong-hyper-references-after-resetting-chapter-counter)
-\usepackage{amsmath}
-\usepackage{amssymb}
+
+% Use AMS fonts
+\usepackage{amsmath, amssymb}
+
+% Improved Palatino fonts - better unicode support?
+\usepackage{newpxtext,newpxmath}
+
\usepackage{color}
\usepackage{fullpage}
\usepackage{graphics}