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

FriCAS spkg-configure and Feature #35838

Merged
merged 30 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5f383d6
More # optional
mkoeppe Jun 12, 2023
66db7aa
Add # optional - numpy etc.
mkoeppe Mar 6, 2023
753ac98
src/sage/interfaces/tides.py: pycodestyle fix
mkoeppe May 13, 2023
0eb6d0a
Massive modularization fixes
mkoeppe May 17, 2023
8ee15dc
More # optional
mkoeppe May 20, 2023
caa8684
sage.interfaces: Modularization fixes
mkoeppe Jun 1, 2023
2b0112d
More # optional
mkoeppe Jun 12, 2023
fa01165
More # optional
mkoeppe Jun 19, 2023
19a524b
More # optional
mkoeppe Jun 20, 2023
e953197
./sage -fixdoctests --no-test src/sage/interfaces
mkoeppe Jul 13, 2023
85baf28
sage.interfaces: Update # needs
mkoeppe Jul 14, 2023
1393952
src/sage/interfaces: Update file-level doctest tag
mkoeppe Aug 7, 2023
12e2a46
src/sage/interfaces: sage -fixdoctests --only-tags
mkoeppe Aug 8, 2023
0bff9f6
Fix # needs for sagemath-pari
mkoeppe Sep 3, 2023
20b960d
Add # needs
mkoeppe Sep 4, 2023
cd3543c
Update # needs
mkoeppe Sep 23, 2023
f4999b0
more distros for fricas
dimpase Jun 26, 2023
21ab2c7
spkg-configure for fricas
dimpase Jun 26, 2023
467eff9
remove debugging echo
dimpase Jun 27, 2023
6ed8cb0
do not insist on sbcl
dimpase Jun 30, 2023
2fd6098
modify the way to send )quit to fricas
dimpase Jun 30, 2023
ba63341
updated design of feature
dimpase Jul 1, 2023
77b1e7a
better string to match (for various lisps)
dimpase Jul 1, 2023
43c85c8
src/sage/interfaces/fricas.py: Use file-level doctest tag
mkoeppe Nov 17, 2023
9ec6b94
sage.interfaces.expect: Delay construction of command to first use, h…
mkoeppe Nov 17, 2023
26e2e58
src/sage/interfaces/fricas.py: Use the FriCAS feature less eagerly
mkoeppe Nov 17, 2023
b474f0e
sage.interfaces.expect: Fix up ulimit
mkoeppe Nov 18, 2023
256bb8c
sage.interfaces.expect: Update doctest output
mkoeppe Nov 18, 2023
ace41e4
src/sage/interfaces/fricas.py: Do not rely on '# tol' for complex tol…
mkoeppe Nov 18, 2023
870fa22
src/sage/functions/special.py: Use 'abs tol' instead of 'tol' in two …
mkoeppe Nov 18, 2023
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
1 change: 1 addition & 0 deletions build/pkgs/fricas/distros/debian.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fricas
1 change: 1 addition & 0 deletions build/pkgs/fricas/distros/freebsd.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
math/fricas
1 change: 1 addition & 0 deletions build/pkgs/fricas/distros/gentoo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sci-mathematics/fricas
1 change: 1 addition & 0 deletions build/pkgs/fricas/distros/opensuse.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fricas
16 changes: 16 additions & 0 deletions build/pkgs/fricas/spkg-configure.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
SAGE_SPKG_CONFIGURE(
[fricas], [
AC_CACHE_CHECK([for FriCAS >= 1.3.8], [ac_cv_path_FRICAS], [
Copy link
Contributor

Choose a reason for hiding this comment

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

the indentation is a bit wild

AC_PATH_PROGS_FEATURE_CHECK([FRICAS], [fricas], [
fricas_version=`echo ")quit" | $ac_path_FRICAS -nox -noclef | grep Version | tail -1 2>&1 \
| $SED -n -e 's/.* Version: FriCAS //p'`
AS_IF([test -n "$fricas_version"], [
AX_COMPARE_VERSION([$fricas_version], [ge], [1.3.8], [
ac_cv_path_FRICAS="$ac_path_FRICAS"
ac_path_FRICAS_found=:
])
])
])
])
AS_IF([test -z "$ac_cv_path_FRICAS"], [sage_spkg_install_fricas=yes])
])
65 changes: 65 additions & 0 deletions src/sage/features/fricas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
r"""
Features for testing the presence of ``fricas``
"""

# *****************************************************************************
# Copyright (C) 2023 Dima Pasechnik
#
# Distributed under the terms of the GNU General Public License (GPL)
# as published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
# https://www.gnu.org/licenses/
# *****************************************************************************

import os
import subprocess
from . import Executable, FeatureTestResult

class FriCAS(Executable):
r"""
A :class:`~sage.features.Feature` which checks for the :ref:`fricas <fricas>` binary.

EXAMPLES::

sage: from sage.features.fricas import FriCAS
sage: FriCAS().is_present() # optional - fricas
FeatureTestResult('fricas', True)
"""
def __init__(self):
r"""
TESTS::

sage: from sage.features.fricas import FriCAS
sage: isinstance(FriCAS(), FriCAS)
True
"""
Executable.__init__(self, name="fricas", spkg="fricas",
executable="fricas",
url="https://fricas.github.io")

def is_functional(self):
r"""
Check whether ``fricas`` works on trivial input.

EXAMPLES::

sage: from sage.features.fricas import FriCAS
sage: FriCAS().is_functional() # optional - fricas
FeatureTestResult('fricas', True)
"""
command = ['fricas -nosman -eval ")quit"']
try:
lines = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as e:
return FeatureTestResult(self, False,

Check warning on line 54 in src/sage/features/fricas.py

View check run for this annotation

Codecov / codecov/patch

src/sage/features/fricas.py#L50-L54

Added lines #L50 - L54 were not covered by tests
reason="Call `{command}` failed with exit code {e.returncode}".format(command=" ".join(command), e=e))

expected = b"FriCAS"
if lines.find(expected) == -1:
return FeatureTestResult(self, False,

Check warning on line 59 in src/sage/features/fricas.py

View check run for this annotation

Codecov / codecov/patch

src/sage/features/fricas.py#L57-L59

Added lines #L57 - L59 were not covered by tests
reason="Call `{command}` did not produce output which contains `{expected}`".format(command=" ".join(command), expected=expected))

return FeatureTestResult(self, True)

Check warning on line 62 in src/sage/features/fricas.py

View check run for this annotation

Codecov / codecov/patch

src/sage/features/fricas.py#L62

Added line #L62 was not covered by tests

def all_features():
return [FriCAS()]
8 changes: 4 additions & 4 deletions src/sage/functions/special.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ def __init__(self):
Check that :trac:`34085` is fixed::

sage: _ = var("x y") # needs sage.symbolic
sage: fricas(elliptic_e(x, y)) # optional - fricas, needs sage.symbolic
sage: fricas(elliptic_e(x, y)) # optional - fricas, needs sage.symbolic
ellipticE(sin(x),y)

However, the conversion is only correct in the interval
Expand All @@ -525,7 +525,7 @@ def __init__(self):
sage: f = lambda x, y: elliptic_e(arcsin(x), y).subs(x=x, y=y)
sage: g = lambda x, y: fricas.ellipticE(x, y).sage()
sage: d = lambda x, y: f(x, y) - g(x, y)
sage: [d(N(-pi/2 + x), y) # tol 1e-8 # optional - fricas, needs sage.symbolic
sage: [d(N(-pi/2 + x), y) # abs tol 1e-8 # optional - fricas, needs sage.symbolic
....: for x in range(1, 3) for y in range(-2, 2)]
[0.000000000000000,
0.000000000000000,
Expand Down Expand Up @@ -877,7 +877,7 @@ def __init__(self):
Check that :trac:`34186` is fixed::

sage: _ = var("x y") # needs sage.symbolic
sage: fricas(elliptic_f(x, y)) # optional - fricas, needs sage.symbolic
sage: fricas(elliptic_f(x, y)) # optional - fricas, needs sage.symbolic
ellipticF(sin(x),y)

However, the conversion is only correct in the interval
Expand All @@ -891,7 +891,7 @@ def __init__(self):
sage: f = lambda x, y: elliptic_f(arcsin(x), y).subs(x=x, y=y)
sage: g = lambda x, y: fricas.ellipticF(x, y).sage()
sage: d = lambda x, y: f(x, y) - g(x, y)
sage: [d(N(-pi/2 + x), y) # tol 1e-8 # optional - fricas, needs sage.symbolic
sage: [d(N(-pi/2 + x), y) # abs tol 1e-8 # optional - fricas, needs sage.symbolic
....: for x in range(1, 3) for y in range(-2,2)]
[0.000000000000000,
0.000000000000000,
Expand Down
105 changes: 57 additions & 48 deletions src/sage/interfaces/axiom.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,12 +304,13 @@ def _commands(self):

EXAMPLES::

sage: cmds = axiom._commands() #optional - axiom
sage: len(cmds) > 100 #optional - axiom
sage: # optional - axiom
sage: cmds = axiom._commands()
sage: len(cmds) > 100
True
sage: '<' in cmds #optional - axiom
sage: '<' in cmds
True
sage: 'factor' in cmds #optional - axiom
sage: 'factor' in cmds
True
"""
s = self.eval(")what things")
Expand All @@ -327,18 +328,19 @@ def _tab_completion(self, verbose=True, use_disk_cache=True):

EXAMPLES::

sage: c = axiom._tab_completion(use_disk_cache=False, verbose=False) #optional - axiom
sage: len(c) > 100 #optional - axiom
sage: # optional - axiom
sage: c = axiom._tab_completion(use_disk_cache=False, verbose=False)
sage: len(c) > 100
True
sage: 'factor' in c #optional - axiom
sage: 'factor' in c
True
sage: '**' in c #optional - axiom
sage: '**' in c
False
sage: 'upperCase?' in c #optional - axiom
sage: 'upperCase?' in c
False
sage: 'upperCase_q' in c #optional - axiom
sage: 'upperCase_q' in c
True
sage: 'upperCase_e' in c #optional - axiom
sage: 'upperCase_e' in c
True
"""
try:
Expand Down Expand Up @@ -396,11 +398,12 @@ def get(self, var):

EXAMPLES::

sage: axiom.set('xx', '2') #optional - axiom
sage: axiom.get('xx') #optional - axiom
sage: # optional - axiom
sage: axiom.set('xx', '2')
sage: axiom.get('xx')
'2'
sage: a = axiom('(1 + sqrt(2))^5') #optional - axiom
sage: axiom.get(a.name()) #optional - axiom
sage: a = axiom('(1 + sqrt(2))^5')
sage: axiom.get(a.name())
' +-+\r\r\n 29\\|2 + 41'
"""
s = self._eval_line(str(var))
Expand Down Expand Up @@ -571,26 +574,28 @@ def _richcmp_(self, other, op):
"""
EXAMPLES::

sage: two = axiom(2) #optional - axiom
sage: two == 2 #optional - axiom
sage: # optional - axiom
sage: two = axiom(2)
sage: two == 2
True
sage: two == 3 #optional - axiom
sage: two == 3
False
sage: two < 3 #optional - axiom
sage: two < 3
True
sage: two > 1 #optional - axiom
sage: two > 1
True

sage: a = axiom(1); b = axiom(2) #optional - axiom
sage: a == b #optional - axiom
sage: # optional - axiom
sage: a = axiom(1); b = axiom(2)
sage: a == b
False
sage: a < b #optional - axiom
sage: a < b
True
sage: a > b #optional - axiom
sage: a > b
False
sage: b < a #optional - axiom
sage: b < a
False
sage: b > a #optional - axiom
sage: b > a
True

We can also compare more complicated object such as functions::
Expand Down Expand Up @@ -649,15 +654,16 @@ def __getitem__(self, n):

EXAMPLES::

sage: v = axiom('[i*x^i for i in 0..5]'); v # optional - axiom
sage: # optional - axiom
sage: v = axiom('[i*x^i for i in 0..5]'); v
2 3 4 5
[0,x,2x ,3x ,4x ,5x ]
sage: v[4] # optional - axiom
sage: v[4]
3
3x
sage: v[1] # optional - axiom
sage: v[1]
0
sage: v[10] # optional - axiom
sage: v[10]
Traceback (most recent call last):
...
IndexError: index out of range
Expand All @@ -677,12 +683,13 @@ def comma(self, *args):

EXAMPLES::

sage: two = axiom(2) #optional - axiom
sage: two.comma(3) #optional - axiom
sage: # optional - axiom
sage: two = axiom(2)
sage: two.comma(3)
[2,3]
sage: two.comma(3,4) #optional - axiom
sage: two.comma(3,4)
[2,3,4]
sage: _.type() #optional - axiom
sage: _.type()
Tuple PositiveInteger
"""
P = self._check_valid()
Expand Down Expand Up @@ -796,12 +803,12 @@ def _sage_(self):
2.12340000000000
sage: _.parent() #optional - axiom
Real Field with 53 bits of precision
sage: a = RealField(100)(pi)
sage: axiom(a)._sage_() #optional - axiom
sage: a = RealField(100)(pi) # needs sage.symbolic
sage: axiom(a)._sage_() # optional - axiom # needs sage.symbolic
3.1415926535897932384626433833
sage: _.parent() #optional - axiom
sage: _.parent() # optional - axiom # needs sage.symbolic
Real Field with 100 bits of precision
sage: axiom(a)._sage_() == a #optional - axiom
sage: axiom(a)._sage_() == a # optional - axiom # needs sage.symbolic
True
sage: axiom(2.0)._sage_() #optional - axiom
2.00000000000000
Expand All @@ -810,16 +817,17 @@ def _sage_(self):


We can also convert Axiom's polynomials to Sage polynomials.
sage: a = axiom(x^2 + 1) #optional - axiom
sage: a.type() #optional - axiom
sage: # optional - axiom, needs sage.symbolic
sage: a = axiom(x^2 + 1)
sage: a.type()
Polynomial Integer
sage: a.sage() #optional - axiom
sage: a.sage()
x^2 + 1
sage: _.parent() #optional - axiom
sage: _.parent()
Univariate Polynomial Ring in x over Integer Ring
sage: axiom('x^2 + y^2 + 1/2').sage() #optional - axiom
sage: axiom('x^2 + y^2 + 1/2').sage()
y^2 + x^2 + 1/2
sage: _.parent() #optional - axiom
sage: _.parent()
Multivariate Polynomial Ring in y, x over Rational Field


Expand Down Expand Up @@ -902,12 +910,13 @@ def __init__(self, object, name):
"""
TESTS::

sage: a = axiom('"Hello"') #optional - axiom
sage: a.upperCase_q #optional - axiom
sage: # optional - axiom
sage: a = axiom('"Hello"')
sage: a.upperCase_q
upperCase?
sage: a.upperCase_e #optional - axiom
sage: a.upperCase_e
upperCase!
sage: a.upperCase_e() #optional - axiom
sage: a.upperCase_e()
"HELLO"
"""
if name.endswith("_q"):
Expand Down
Loading
Loading