Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

apply->eval and doc stuff #740

Merged
merged 2 commits into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion mathics/builtin/attributes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""
Attributes of Definitions
Definition Attributes

While a definition like 'cube[$x_$] = $x$^3' gives a way to specify \
<em>values</em> of a function, <em>attributes</em> allow a way to \
Expand All @@ -13,6 +13,9 @@
However in contrast to \Mathematica, you can set any symbol as an attribute.
"""

# This tells documentation how to sort this module
sort_order = "mathics.builtin.definition-attributes"


from mathics.builtin.base import Builtin, Predefined
from mathics.core.assignment import get_symbol_list
Expand Down
30 changes: 22 additions & 8 deletions mathics/builtin/functional/composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,35 @@
"""
Functional Composition and Operator Forms

<url>:Functional Composition: https://en.wikipedia.org/wiki/Function_composition_(computer_science)</url> is a way to combine simple functions to build more complicated ones.
Like the usual composition of functions in mathematics, the result of each function is passed as the argument of the next, and the result of the last one is the result of the whole.

The symbolic structure of Mathics makes it easy to create "operators" that can be composed and manipulated symbolically—forming "pipelines" of operations—and then applied to arguments.

Some built-in functions also directly support a "curried" form, in which they can immediately be given as symbolic operators.
<url>:Functional Composition:
https://en.wikipedia.org/wiki/Function_composition_(computer_science)</url> is \
a way to combine simple functions to build more complicated ones.
Like the usual composition of functions in mathematics, the result of each \
function is passed as the argument of the next, and the result of the last \
one is the result of the whole.

The symbolic structure of Mathics3 makes it easy to create "operators" that \
can be composed and manipulated symbolically—forming "pipelines" of \
operations—and then applied to arguments.

Some built-in functions also directly support a "curried" form, in which they \
can immediately be given as symbolic operators.
"""

# This tells documentation how to sort this module
sort_order = "mathics.builtin.functional-composition"

from mathics.builtin.base import Builtin
from mathics.core.attributes import A_FLAT, A_ONE_IDENTITY, A_PROTECTED
from mathics.core.expression import Expression
from mathics.core.expression import Evaluation, Expression
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Evaluation comes from the module mathis.core.evaluation.



class Composition(Builtin):
"""
<url>
:WMA link:
https://reference.wolfram.com/language/ref/Composition.html</url>

<dl>
<dt>'Composition[$f$, $g$]'
<dd>returns the composition of two functions $f$ and $g$.
Expand All @@ -47,7 +58,7 @@ class Composition(Builtin):
}
summary_text = "the composition of two or more functions"

def apply(self, functions, args, evaluation):
def eval(self, functions, args, evaluation: Evaluation):
"Composition[functions__][args___]"

functions = functions.get_sequence()
Expand All @@ -60,6 +71,9 @@ def apply(self, functions, args, evaluation):

class Identity(Builtin):
"""
<url>
:WMA link:
https://reference.wolfram.com/language/ref/Identity.html</url>
<dl>
<dt>'Identity[$x$]'
<dd>is the identity function, which returns $x$ unchanged.
Expand Down
7 changes: 5 additions & 2 deletions mathics/builtin/inout.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from mathics.builtin.base import Builtin, Predefined
from mathics.core.attributes import A_NO_ATTRIBUTES
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
from mathics.core.list import ListExpression
from mathics.core.symbols import Symbol, SymbolNull
Expand Down Expand Up @@ -37,7 +38,9 @@ class Echo_(Predefined):

class Print(Builtin):
"""
<url>:WMA link:https://reference.wolfram.com/language/ref/Print.html</url>
<url>
:WMA link:
https://reference.wolfram.com/language/ref/Print.html</url>

<dl>
<dt>'Print[$expr$, ...]'
Expand All @@ -56,7 +59,7 @@ class Print(Builtin):

summary_text = "print strings and formatted text"

def apply(self, expr, evaluation):
def eval(self, expr, evaluation: Evaluation):
"Print[expr__]"

expr = expr.get_sequence()
Expand Down
55 changes: 34 additions & 21 deletions mathics/builtin/intfns/divlike.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,32 @@
)
from mathics.core.convert.expression import to_mathics_list
from mathics.core.convert.python import from_bool
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
from mathics.core.symbols import Symbol, SymbolFalse, SymbolTrue
from mathics.core.systemsymbols import SymbolComplexInfinity

SymbolQuotient = Symbol("Quotient")
SymbolQuotientRemainder = Symbol("QuotientRemainder")
from mathics.core.symbols import SymbolFalse, SymbolTrue
from mathics.core.systemsymbols import (
SymbolComplexInfinity,
SymbolQuotient,
SymbolQuotientRemainder,
)


class CompositeQ(Builtin):
"""
<url>:WMA link:https://reference.wolfram.com/language/ref/CompositeQ.html</url>
<url>
:WMA link:
https://reference.wolfram.com/language/ref/CompositeQ.html</url>

<dl>
<dt>'CompositeQ[$n$]'
<dd>returns True if $n$ is a composite number
</dl>

<ul>
<li>A composite number is a positive number that is the product of two integers other than 1.
<li>For negative integer $n$, 'CompositeQ[$n$]' is effectively equivalent to 'CompositeQ[-$n$]'.
<li>A composite number is a positive number that is the product of two \
integers other than 1.
<li>For negative integer $n$, 'CompositeQ[$n$]' is effectively equivalent \
to 'CompositeQ[-$n$]'.
</ul>

>> Table[CompositeQ[n], {n, 0, 10}]
Expand All @@ -52,7 +58,7 @@ class CompositeQ(Builtin):
attributes = A_LISTABLE | A_PROTECTED
summary_text = "test whether a number is composite"

def apply(self, n, evaluation):
def eval(self, n: Integer, evaluation: Evaluation):
"CompositeQ[n_Integer]"
return from_bool(ask(Q.composite(n.value)))

Expand All @@ -63,7 +69,8 @@ class CoprimeQ(Builtin):

<dl>
<dt>'CoprimeQ[$x$, $y$]'
<dd>tests whether $x$ and $y$ are coprime by computing their greatest common divisor.
<dd>tests whether $x$ and $y$ are coprime by computing their greatest \
common divisor.
</dl>

>> CoprimeQ[7, 9]
Expand Down Expand Up @@ -92,7 +99,7 @@ class CoprimeQ(Builtin):
attributes = A_LISTABLE | A_PROTECTED
summary_text = "test whether elements are coprime"

def apply(self, args, evaluation):
def eval(self, args, evaluation: Evaluation):
"CoprimeQ[args__]"

py_args = [arg.to_python() for arg in args.get_sequence()]
Expand Down Expand Up @@ -183,7 +190,7 @@ class GCD(Builtin):
attributes = A_FLAT | A_LISTABLE | A_ONE_IDENTITY | A_ORDERLESS | A_PROTECTED
summary_text = "greatest common divisor"

def apply(self, ns, evaluation):
def eval(self, ns, evaluation: Evaluation):
"GCD[ns___Integer]"

ns = ns.get_sequence()
Expand Down Expand Up @@ -214,7 +221,7 @@ class LCM(Builtin):
attributes = A_FLAT | A_LISTABLE | A_ONE_IDENTITY | A_ORDERLESS | A_PROTECTED
summary_text = "least common multiple"

def apply(self, ns: List[Integer], evaluation):
def eval(self, ns: List[Integer], evaluation: Evaluation):
"LCM[ns___Integer]"

ns = ns.get_sequence()
Expand Down Expand Up @@ -250,7 +257,7 @@ class Mod(Builtin):
attributes = A_LISTABLE | A_NUMERIC_FUNCTION | A_PROTECTED
summary_text = "the remainder in an integer division"

def apply(self, n: Integer, m: Integer, evaluation):
def eval(self, n: Integer, m: Integer, evaluation: Evaluation):
"Mod[n_Integer, m_Integer]"

n, m = n.value, m.value
Expand All @@ -262,14 +269,20 @@ def apply(self, n: Integer, m: Integer, evaluation):

class ModularInverse(SympyFunction):
"""
<url>:Modular multiplicative inverse: https://en.wikipedia.org/wiki/Modular_multiplicative_inverse</url> (<url>:SymPy: https://docs.sympy.org/latest/modules/core.html#sympy.core.numbers.mod_inverse</url>, <url>:WMA: https://reference.wolfram.com/language/ref/ModularInverse.html</url>)
<url>
:Modular multiplicative inverse:
https://en.wikipedia.org/wiki/Modular_multiplicative_inverse</url> (<url>
:SymPy: https://docs.sympy.org/latest/modules/core.html#sympy.core.numbers.mod_inverse</url>, <url>
:WMA: https://reference.wolfram.com/language/ref/ModularInverse.html
</url>)

<dl>
<dt>'ModularInverse[$k$, $n$]'
<dd>returns the modular inverse $k$^(-1) mod $n$.
</dl>

'ModularInverse[$k$,$n$]' gives the smallest positive integer $r$ where the remainder of the division of $r$ x $k$ by $n$ is equal to 1.
'ModularInverse[$k$,$n$]' gives the smallest positive integer $r$ where the remainder \
of the division of $r$ x $k$ by $n$ is equal to 1.

>> ModularInverse[2, 3]
= 2
Expand All @@ -289,7 +302,7 @@ class ModularInverse(SympyFunction):
summary_text = "returns the modular inverse $k^(-1)$ mod $n$"
sympy_name = "mod_inverse"

def apply_k_n(self, k: Integer, n: Integer, evaluation):
def eval_k_n(self, k: Integer, n: Integer, evaluation: Evaluation):
"ModularInverse[k_Integer, n_Integer]"
try:
r = sympy.mod_inverse(k.value, n.value)
Expand Down Expand Up @@ -352,7 +365,7 @@ class PowerMod(Builtin):
}
summary_text = "modular exponentiation"

def apply(self, a: Integer, b: Integer, m: Integer, evaluation):
def eval(self, a: Integer, b: Integer, m: Integer, evaluation: Evaluation):
"PowerMod[a_Integer, b_Integer, m_Integer]"

a_int = a
Expand Down Expand Up @@ -411,7 +424,7 @@ class PrimeQ(SympyFunction):
sympy_name = "isprime"
summary_text = "test whether elements are prime numbers"

def apply(self, n, evaluation):
def eval(self, n, evaluation: Evaluation):
"PrimeQ[n_]"

n = n.get_int_value()
Expand Down Expand Up @@ -455,7 +468,7 @@ class Quotient(Builtin):
}
summary_text = "integer quotient"

def apply(self, m: Integer, n: Integer, evaluation):
def eval(self, m: Integer, n: Integer, evaluation: Evaluation):
"Quotient[m_Integer, n_Integer]"
py_m = m.value
py_n = n.value
Expand Down Expand Up @@ -503,7 +516,7 @@ class QuotientRemainder(Builtin):
}
summary_text = "integer quotient and remainder"

def apply(self, m, n, evaluation):
def eval(self, m, n, evaluation: Evaluation):
"QuotientRemainder[m_, n_]"
if m.is_numeric(evaluation) and n.is_numeric():
py_m = m.to_python()
Expand Down
41 changes: 27 additions & 14 deletions mathics/builtin/intfns/recurrence.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
"""
Recurrence and Sum Functions

A recurrence relation is an equation that recursively defines a sequence or multidimensional array of values, once one or more initial terms are given; each further term of the sequence or array is defined as a function of the preceding terms.
A recurrence relation is an equation that recursively defines a \
sequence or multidimensional array of values, once one or more initial \
terms are given; each further term of the sequence or array is defined \
as a function of the preceding terms.
"""


Expand All @@ -17,6 +20,7 @@
A_PROTECTED,
A_READ_PROTECTED,
)
from mathics.core.evaluation import Evaluation


class Fibonacci(_MPMathFunction):
Expand Down Expand Up @@ -51,7 +55,7 @@ class HarmonicNumber(_MPMathFunction):
<url>:WMA link:https://reference.wolfram.com/language/ref/HarmonicNumber.html</url>)

<dl>
<dt>'HarmonicNumber[n]'
<dt>'HarmonicNumber[n]'
<dd>returns the $n$th harmonic number.
</dl>

Expand All @@ -76,8 +80,12 @@ class HarmonicNumber(_MPMathFunction):
# Note: WL allows StirlingS1[{2, 4, 6}, 2], but we don't (yet).
class StirlingS1(Builtin):
"""
<url>:Stirling numbers of first kind:https://en.wikipedia.org/wiki/Stirling_numbers_of_the_first_kind</url> \
(<url>:WMA link:https://reference.wolfram.com/language/ref/StirlingS1.html</url>)
<url>
:Stirling numbers of first kind:
https://en.wikipedia.org/wiki/Stirling_numbers_of_the_first_kind</url> \
(<url>
:WMA link:
https://reference.wolfram.com/language/ref/StirlingS1.html</url>)

<dl>
<dt>'StirlingS1[$n$, $m$]'
Expand All @@ -98,24 +106,29 @@ class StirlingS1(Builtin):
sympy_name = "functions.combinatorial.stirling"
mpmath_name = "stirling1"

def apply(self, n, m, evaluation):
def eval(self, n: Integer, m: Integer, evaluation: Evaluation):
"%(name)s[n_Integer, m_Integer]"
n_value = n.get_int_value()
m_value = m.get_int_value()
n_value = n.value
m_value = m.value
return Integer(stirling(n_value, m_value, kind=1, signed=True))


class StirlingS2(Builtin):
"""
<url>:Stirling numbers of first kind:https://en.wikipedia.org/wiki/Stirling_numbers_of_the_second_kind</url> \
(<url>:WMA link:https://reference.wolfram.com/language/ref/StirlingS2.html</url>)
<url>
:Stirling numbers of second kind:
https://en.wikipedia.org/wiki/Stirling_numbers_of_the_second_kind</url> \
(<url>
:WMA link
:https://reference.wolfram.com/language/ref/StirlingS2.html</url>)

<dl>
<dl>
<dt>'StirlingS2[$n$, $m$]'
<dd>gives the Stirling number of the second kind _n^m.
</dl>

returns the number of ways of partitioning a set of $n$ elements into $m$ non empty subsets.
returns the number of ways of partitioning a set of $n$ elements into $m$ \
non empty subsets.

>> Table[StirlingS2[10, m], {m, 10}]
= {1, 511, 9330, 34105, 42525, 22827, 5880, 750, 45, 1}
Expand All @@ -127,8 +140,8 @@ class StirlingS2(Builtin):
mpmath_name = "stirling2"
summary_text = "Stirling numbers of the second kind"

def apply(self, m, n, evaluation):
def eval(self, m: Integer, n: Integer, evaluation: Evaluation):
"%(name)s[n_Integer, m_Integer]"
n_value = n.get_int_value()
m_value = m.get_int_value()
n_value = n.value
m_value = m.value
return Integer(stirling(n_value, m_value, kind=2))
2 changes: 2 additions & 0 deletions mathics/core/systemsymbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@
SymbolPrecision = Symbol("System`Precision")
SymbolQuantity = Symbol("System`Quantity")
SymbolQuiet = Symbol("System`Quiet")
SymbolQuotient = Symbol("System`Quotient")
SymbolQuotientRemainder = Symbol("System`QuotientRemainder")
SymbolRGBColor = Symbol("System`RGBColor")
SymbolRandomComplex = Symbol("System`RandomComplex")
SymbolRandomReal = Symbol("System`RandomReal")
Expand Down