Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
36 changes: 10 additions & 26 deletions mathics/builtin/intfns/divlike.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""

import sys
from typing import List
from typing import List, Optional

import sympy
from sympy import Q, ask
Expand All @@ -30,6 +30,7 @@
SymbolQuotient,
SymbolQuotientRemainder,
)
from mathics.eval.intfns.divlike import eval_GCD, eval_LCM, eval_ModularInverse


class CompositeQ(Builtin):
Expand Down Expand Up @@ -121,17 +122,10 @@ class GCD(Builtin):
attributes = A_FLAT | A_LISTABLE | A_ONE_IDENTITY | A_ORDERLESS | A_PROTECTED
summary_text = "greatest common divisor"

def eval(self, ns, evaluation: Evaluation):
def eval(self, ns, evaluation: Evaluation) -> Optional[Integer]:
"GCD[ns___Integer]"

ns = ns.get_sequence()
result = 0
for n in ns:
value = n.value
if value is None:
return
result = sympy.gcd(result, value)
return Integer(result)
return eval_GCD(ns.get_sequence())


class LCM(Builtin):
Expand All @@ -157,20 +151,14 @@ class LCM(Builtin):
}
summary_text = "least common multiple"

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

ns = ns.get_sequence()
if len(ns) == 0:
ns_tuple = ns.get_sequence()
if len(ns_tuple) == 0:
evaluation.message("LCM", "argm")
return
result = 1
for n in ns:
value = n.value
if value is None:
return
result = sympy.lcm(result, value)
return Integer(result)
return eval_LCM(ns_tuple)


class Mod(SympyFunction):
Expand Down Expand Up @@ -247,13 +235,9 @@ class ModularInverse(SympyFunction):
summary_text = "returns the modular inverse $k^(-1)$ mod $n$"
sympy_name = "mod_inverse"

def eval_k_n(self, k: Integer, n: Integer, evaluation: Evaluation):
def eval(self, k: Integer, n: Integer, evaluation: Evaluation) -> Optional[Integer]:
"ModularInverse[k_Integer, n_Integer]"
try:
r = sympy.mod_inverse(k.value, n.value)
except ValueError:
return
return Integer(r)
return eval_ModularInverse(k.value, n.value)


class PowerMod(Builtin):
Expand Down
48 changes: 0 additions & 48 deletions mathics/builtin/intfns/misc.py

This file was deleted.

139 changes: 95 additions & 44 deletions mathics/builtin/intfns/recurrence.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
as a function of the preceding terms.
"""


from sympy.functions.combinatorial.numbers import stirling

import mathics.eval.tracing as tracing
from mathics.core.atoms import Integer
from mathics.core.attributes import (
A_LISTABLE,
Expand All @@ -22,46 +22,91 @@
from mathics.core.evaluation import Evaluation


class Fibonacci(MPMathFunction):
class BernoulliB(MPMathFunction):
"""
<url>
:Fibonacci Sequence:
https://en.wikipedia.org/wiki/Fibonacci_sequence</url>, <url>(
:WMA link:https://reference.wolfram.com/language/ref/Fibonacci.html</url>)
<url>:Bernoulli number:
https://en.wikipedia.org/wiki/Bernoulli_number</url> (<url>:WMA link:https://reference.wolfram.com/language/ref/BernoulliB.html</url>)

<dl>
<dt>'Fibonacci'[$n$]
<dd>computes the $n$-th Fibonacci number.
<dt>'Fibonacci'[$n$, $x$]
<dd>computes the Fibonacci polynomial $F_n(x)$.
</dl>
<dl>
<dt>'BernoulliB'[$n$]
<dd>represents the Bernoulli number $B_n$.

>> Fibonacci[0]
= 0
>> Fibonacci[1]
= 1
>> Fibonacci[10]
= 55
>> Fibonacci[200]
= 280571172992510140037611932413038677189525
>> Fibonacci[7, x]
= 1 + 6 x ^ 2 + 5 x ^ 4 + x ^ 6
<dt>'BernouilliB'[$n$, $x$]
<dd>represents the Bernoulli polynomial $B_n(x)$.
</dl>

See also <url>
:LinearRecurrence:
/doc/reference-of-built-in-symbols/integer-functions/recurrence-and-sum-functions/linearrecurrence</url>.
>> BernoulliB[42]
= 1520097643918070802691 / 1806

First five Bernoulli numbers:

>> Table[BernoulliB[k], {k, 0, 5}]
= ...

## This must be (according to WMA)
## = {1, -1 / 2, 1 / 6, 0, -1 / 30, 0}
## but for some reason, in the CI the previous test produces
## the output:
## {1, 1 / 2, 1 / 6, 0, -1 / 30, 0}

First five Bernoulli polynomials:

>> Table[BernoulliB[k, z], {k, 0, 3}]
= {1, -1 / 2 + z, 1 / 6 - z + z ^ 2, z / 2 - 3 z ^ 2 / 2 + z ^ 3}
"""

attributes = A_LISTABLE | A_PROTECTED
eval_error = Builtin.generic_argument_error
expected_args = (1, 2)
mpmath_name = "bernoulli"
nargs = {1, 2}
summary_text = "Bernoulli numbers and polynomials"
sympy_name = "bernoulli"


class Fibonacci(MPMathFunction):
"""
<url>
:Fibonacci Sequence:
https://en.wikipedia.org/wiki/Fibonacci_sequence</url> and <url>
:Fibonacci polynomials:
https://en.wikipedia.org/wiki/Fibonacci_polynomials</url> (<url>
:WMA link:https://reference.wolfram.com/language/ref/Fibonacci.html</url>)

<dl>
<dt>'Fibonacci'[$n$]
<dd>computes the $n$-th Fibonacci number.
<dt>'Fibonacci'[$n$, $x$]
<dd>computes the Fibonacci polynomial $F_n(x)$.
</dl>

>> Fibonacci[0]
= 0
>> Fibonacci[1]
= 1
>> Fibonacci[10]
= 55
>> Fibonacci[200]
= 280571172992510140037611932413038677189525
>> Fibonacci[7, x]
= 1 + 6 x ^ 2 + 5 x ^ 4 + x ^ 6

See also <url>
:LinearRecurrence:
/doc/reference-of-built-in-symbols/integer-functions/recurrence-and-sum-functions/linearrecurrence</url>.
"""

nargs = {1}
attributes = A_LISTABLE | A_NUMERIC_FUNCTION | A_PROTECTED | A_READ_PROTECTED
sympy_name = "fibonacci"
eval_error = Builtin.generic_argument_error
expected_args = (1, 2)
mpmath_name = "fibonacci"
summary_text = "Fibonacci's numbers"

nargs = {1}
rules = {
"Fibonacci[0, x_]": "0",
"Fibonacci[n_Integer?Negative, x_]": "Fibonacci[-n, x]",
}
summary_text = "Fibonacci sequences and polynomials"
sympy_name = "fibonacci"


class HarmonicNumber(MPMathFunction):
Expand All @@ -81,19 +126,22 @@ class HarmonicNumber(MPMathFunction):
= 2.03806
"""

attributes = A_LISTABLE | A_NUMERIC_FUNCTION | A_READ_PROTECTED | A_PROTECTED
eval_error = Builtin.generic_argument_error
expected_args = (1, 2)
mpmath_name = "harmonic"
rules = {
"HarmonicNumber[-1]": "ComplexInfinity",
}
summary_text = "Harmonic numbers"
mpmath_name = "harmonic"
sympy_name = "harmonic"


class LinearRecurrence(Builtin):
"""
<url>:Linear recurrence with constant coefficients:
https://en.wikipedia.org/wiki/Linear_recurrence_with_constant_coefficients</url>, <url>
:WMA link:https://reference.wolfram.com/language/ref/LinearRecurrence.html</url>
https://en.wikipedia.org/wiki/Linear_recurrence_with_constant_coefficients</url> (<url>
:WMA link:https://reference.wolfram.com/language/ref/LinearRecurrence.html</url>)

<dl>
<dt>'LinearRecurrence'[$ker$, $init$, $n$]
Expand Down Expand Up @@ -124,13 +172,15 @@ class LinearRecurrence(Builtin):
"""

attributes = A_PROTECTED | A_READ_PROTECTED
summary_text = "linear recurrence"
eval_error = Builtin.generic_argument_error
expected_args = 3

rules = {
"LinearRecurrence[ker_List, init_List, n_Integer]": "Nest[Append[#, Reverse[ker] . Take[#, -Length[ker]]] &, init, n - Length[init]]",
"LinearRecurrence[ker_List, init_List, {n_Integer?Positive}]": "LinearRecurrence[ker, init, n][[n]]",
"LinearRecurrence[ker_List, init_List, {nmin_Integer?Positive, nmax_Integer?Positive}]": "LinearRecurrence[ker, init, nmax][[nmin;;nmax]]",
}
summary_text = "linear recurrence"


# Note: WL allows StirlingS1[{2, 4, 6}, 2], but we don't (yet).
Expand All @@ -155,17 +205,18 @@ class StirlingS1(Builtin):
"""

attributes = A_LISTABLE | A_PROTECTED

eval_error = Builtin.generic_argument_error
expected_args = 2
mpmath_name = "stirling1"
nargs = {2}
summary_text = "Stirling numbers of the first kind"
sympy_name = "functions.combinatorial.stirling"
mpmath_name = "stirling1"

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


class StirlingS2(Builtin):
Expand All @@ -188,13 +239,13 @@ class StirlingS2(Builtin):
"""

attributes = A_LISTABLE | A_PROTECTED
nargs = {2}
eval_error = Builtin.generic_argument_error
expected_args = 2
sympy_name = "functions.combinatorial.numbers.stirling"
mpmath_name = "stirling2"
nargs = {2}
summary_text = "Stirling numbers of the second kind"

def eval(self, m: Integer, n: Integer, evaluation: Evaluation):
"%(name)s[n_Integer, m_Integer]"
n_value = n.value
m_value = m.value
return Integer(stirling(n_value, m_value, kind=2))
"StirlingS2[n_Integer, m_Integer]"
return Integer(tracing.run_sympy(stirling, n.value, m.value, kind=2))
2 changes: 1 addition & 1 deletion mathics/eval/hyperbolic.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Mathics3 builtins from mathics.core.numbers.hyperbolic
Mathics3 builtins from mathics.builtin.numbers.hyperbolic
"""

from sympy import Symbol as SympySymbol
Expand Down
3 changes: 3 additions & 0 deletions mathics/eval/intfns/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""
Evaluation functions associated with mathics.builtin.intfns.
"""
Loading
Loading