From 0be33006cf8ea4f90d4d69662c0679205b330648 Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 4 Aug 2024 14:39:44 -0400 Subject: [PATCH 1/5] Misc doc-related changes numbers.py: Precision; fix spelling, remove hard line-wrap and make render in LaTeX better symbols.py: Need \n after . Hash was not doctest'd properly combinatorial.py: Add Subset link; shorten Subset test output, constants.py: better Infinity exmaples, link to DirectedInfinity orderstats. WMA -> WMA link (when there are no other links) expression_tests.py: move and *Q here. systemsymbols: More symbols --- mathics/builtin/atomic/numbers.py | 15 ++- mathics/builtin/atomic/symbols.py | 1 + mathics/builtin/exp_structure/general.py | 101 +----------------- mathics/builtin/exp_structure/size_and_sig.py | 12 +-- mathics/builtin/intfns/combinatorial.py | 9 +- mathics/builtin/numbers/constants.py | 23 +++- mathics/builtin/numeric.py | 1 + mathics/builtin/statistics/orderstats.py | 12 ++- .../testing_expressions/expression_tests.py | 97 +++++++++++++++++ mathics/core/systemsymbols.py | 2 + mathics/doc/documentation/1-Manual.mdoc | 3 +- 11 files changed, 149 insertions(+), 127 deletions(-) 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..d78b3152b 100644 --- a/mathics/builtin/exp_structure/general.py +++ b/mathics/builtin/exp_structure/general.py @@ -3,7 +3,7 @@ General Structural Expression Functions """ -from mathics.core.atoms import Integer, Integer0, Integer1, Rational +from mathics.core.atoms import Integer, Rational from mathics.core.builtin import BinaryOperator, Builtin, Predefined from mathics.core.exceptions import InvalidLevelspecError from mathics.core.expression import Evaluation, Expression @@ -406,105 +406,6 @@ def eval(self, p, expr, n, evaluation: Evaluation): 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): """ 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/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..c14097291 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") @@ -230,6 +231,7 @@ SymbolSinh = Symbol("System`Sinh") SymbolSlot = Symbol("System`Slot") SymbolSparseArray = Symbol("System`SparseArray") +SymbolSortBy = Symbol("System`SortBy") SymbolSplit = Symbol("System`Split") SymbolSqrt = Symbol("System`Sqrt") SymbolSqrtBox = Symbol("System`SqrtBox") 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 From 1eb0eb3ffd84e0e1b2f8627b1c31196e8c87aab1 Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 4 Aug 2024 18:25:01 -0400 Subject: [PATCH 2/5] Remove WordCloud tests... we don't know how to install WordCloud on Windows without it giving ImportError: DLL load failed while importing _c_internal_utils: The specified module could not be found. (from matplotlib) --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 5f17a451d24ddbf7b879ee1c34d403b0b77f4a3d Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 4 Aug 2024 19:08:32 -0400 Subject: [PATCH 3/5] Split out Head-Related Structural Operations... on Expressions --- mathics/builtin/exp_structure/general.py | 213 +----------------- mathics/builtin/exp_structure/head_related.py | 102 +++++++++ mathics/core/systemsymbols.py | 2 +- 3 files changed, 106 insertions(+), 211 deletions(-) create mode 100644 mathics/builtin/exp_structure/head_related.py diff --git a/mathics/builtin/exp_structure/general.py b/mathics/builtin/exp_structure/general.py index d78b3152b..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, 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,72 +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 SortBy(Builtin): """ @@ -485,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/core/systemsymbols.py b/mathics/core/systemsymbols.py index c14097291..55bb40960 100644 --- a/mathics/core/systemsymbols.py +++ b/mathics/core/systemsymbols.py @@ -230,8 +230,8 @@ SymbolSin = Symbol("System`Sin") SymbolSinh = Symbol("System`Sinh") SymbolSlot = Symbol("System`Slot") -SymbolSparseArray = Symbol("System`SparseArray") SymbolSortBy = Symbol("System`SortBy") +SymbolSparseArray = Symbol("System`SparseArray") SymbolSplit = Symbol("System`Split") SymbolSqrt = Symbol("System`Sqrt") SymbolSqrtBox = Symbol("System`SqrtBox") From 50cfce1d36791b427b58aea70feba14ac71489dd Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 5 Aug 2024 14:55:50 -0400 Subject: [PATCH 4/5] More doc-related fixes... Add another "\n" at the end of a
Compute number boxwidth automatically in tocbox numbers --- mathics/builtin/graphics.py | 4 +++- mathics/doc/latex/mathics.tex | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) 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/doc/latex/mathics.tex b/mathics/doc/latex/mathics.tex index 0462a6bc1..353216fd3 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. From 8d165c6e79435cfef329a2be08d08b7cbf08cac0 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 6 Aug 2024 09:09:40 -0400 Subject: [PATCH 5/5] Improved Palatino fonts - better unicode support? --- mathics/doc/latex/mathics.tex | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mathics/doc/latex/mathics.tex b/mathics/doc/latex/mathics.tex index 353216fd3..665bdd966 100644 --- a/mathics/doc/latex/mathics.tex +++ b/mathics/doc/latex/mathics.tex @@ -41,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}