diff --git a/.github/workflows/osx.yml b/.github/workflows/osx.yml
index 2269693ac..da640f1b2 100644
--- a/.github/workflows/osx.yml
+++ b/.github/workflows/osx.yml
@@ -9,8 +9,8 @@ on:
jobs:
build:
env:
- LDFLAGS: "-L/usr/local/opt/llvm@11/lib"
- CPPFLAGS: "-I/usr/local/opt/llvm@11/include"
+ LDFLAGS: "-L/usr/local/opt/llvm@14/lib"
+ CPPFLAGS: "-I/usr/local/opt/llvm@14/include"
runs-on: macos-latest
strategy:
matrix:
@@ -24,7 +24,7 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: Install OS dependencies
run: |
- brew install llvm tesseract
+ brew install llvm@14 tesseract
python -m pip install --upgrade pip
- name: Install Mathics3 with full Python dependencies
run: |
diff --git a/AUTHORS.txt b/AUTHORS.txt
index 9dc803a42..03cdcf44b 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -36,6 +36,8 @@ Additional contributions were made by:
- Pablo Emilio Escobar Gaviria @GarkGarcia
- Rocky Bernstein @rocky
- Tiago Cavalcante Trindade @TiagoCavalcante
+- Li Xiang @Li-Xiang-Ideal
+- Kevin Cao @kejcao
Thanks to the authors of all projects that are used in Mathics:
- Django
diff --git a/CHANGES.rst b/CHANGES.rst
index 8e602d47c..2729acab9 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -8,9 +8,11 @@ New Builtins
++++++++++++
-* `Elements`
-* `RealAbs` and `RealSign`
-* `RealValuedNumberQ`
+* ``Elements``
+* ``ConjugateTranspose``
+* ``LeviCivitaTensor``
+* ``RealAbs`` and ``RealSign``
+* ``RealValuedNumberQ``
Compatibility
diff --git a/FUTURE.rst b/FUTURE.rst
index e37758f22..291e016d2 100644
--- a/FUTURE.rst
+++ b/FUTURE.rst
@@ -2,9 +2,11 @@
.. contents::
-The following 2023 road map that appears the 6.0.0 hasn't gone through enough discussion. This provisional.
-Check the github repository for updates.
+2024 Roadmap
+============
+
+To be decided...
2023 Roadmap
============
diff --git a/SYMBOLS_MANIFEST.txt b/SYMBOLS_MANIFEST.txt
index d3ecf4204..43c6e2162 100644
--- a/SYMBOLS_MANIFEST.txt
+++ b/SYMBOLS_MANIFEST.txt
@@ -574,6 +574,7 @@ System`LessEqual
System`LetterCharacter
System`LetterNumber
System`LetterQ
+System`LeviCivitaTensor
System`Level
System`LevelQ
System`LightBlue
diff --git a/admin-tools/make-dist.sh b/admin-tools/make-dist.sh
index 015477da8..d2f045dd0 100755
--- a/admin-tools/make-dist.sh
+++ b/admin-tools/make-dist.sh
@@ -25,7 +25,8 @@ for pyversion in $PYVERSIONS; do
exit $?
fi
rm -fr build
- python setup.py bdist_egg
+ # PYPI no longer supports eggs
+ # python setup.py bdist_egg
python setup.py bdist_wheel
done
diff --git a/mathics/builtin/arithmetic.py b/mathics/builtin/arithmetic.py
index 0f5a329cc..5f622282c 100644
--- a/mathics/builtin/arithmetic.py
+++ b/mathics/builtin/arithmetic.py
@@ -958,14 +958,6 @@ class Sum(IterationFunction, SympyFunction):
Verify algebraic identities:
>> Sum[x ^ 2, {x, 1, y}] - y * (y + 1) * (2 * y + 1) / 6
= 0
-
-
- ## Issue #302
- ## The sum should not converge since the first term is 1/0.
- #> Sum[i / Log[i], {i, 1, Infinity}]
- = Sum[i / Log[i], {i, 1, Infinity}]
- #> Sum[Cos[Pi i], {i, 1, Infinity}]
- = Sum[Cos[i Pi], {i, 1, Infinity}]
"""
summary_text = "discrete sum"
diff --git a/mathics/builtin/distance/clusters.py b/mathics/builtin/distance/clusters.py
index ebd904540..382fce982 100644
--- a/mathics/builtin/distance/clusters.py
+++ b/mathics/builtin/distance/clusters.py
@@ -35,6 +35,7 @@
)
from mathics.eval.nevaluator import eval_N
from mathics.eval.parts import walk_levels
+from mathics.eval.tensors import get_default_distance
class _LazyDistances(LazyDistances):
@@ -139,8 +140,6 @@ def _cluster(self, p, k, mode, evaluation, options, expr):
options, "DistanceFunction", evaluation
)
if distance_function_string == "Automatic":
- from mathics.builtin.tensors import get_default_distance
-
distance_function = get_default_distance(dist_p)
if distance_function is None:
name_of_builtin = strip_context(self.get_name())
@@ -462,8 +461,6 @@ def eval(
options, "DistanceFunction", evaluation
)
if distance_function_string == "Automatic":
- from mathics.builtin.tensors import get_default_distance
-
distance_function = get_default_distance(dist_p)
if distance_function is None:
evaluation.message(
diff --git a/mathics/builtin/files_io/files.py b/mathics/builtin/files_io/files.py
index 2c3272af4..200d53406 100644
--- a/mathics/builtin/files_io/files.py
+++ b/mathics/builtin/files_io/files.py
@@ -204,10 +204,6 @@ class Close(Builtin):
Closing a file doesn't delete it from the filesystem
>> DeleteFile[file];
- #> Close["abc"]
- : abc is not open.
- = Close[abc]
-
#> Clear[file]
"""
@@ -277,18 +273,6 @@ class FilePrint(Builtin):
prints the raw contents of $file$.
- #> exp = Sin[1];
- #> FilePrint[exp]
- : File specification Sin[1] is not a string of one or more characters.
- = FilePrint[Sin[1]]
-
- #> FilePrint["somenonexistentpath_h47sdmk^&h4"]
- : Cannot open somenonexistentpath_h47sdmk^&h4.
- = FilePrint[somenonexistentpath_h47sdmk^&h4]
-
- #> FilePrint[""]
- : File specification is not a string of one or more characters.
- = FilePrint[]
"""
messages = {
@@ -394,16 +378,6 @@ class Get(PrefixOperator):
## TODO: Requires EndPackage implemented
## 'Get' can also load packages:
## >> << "VectorAnalysis`"
-
- #> Get["SomeTypoPackage`"]
- : Cannot open SomeTypoPackage`.
- = $Failed
-
- ## Parser Tests
- #> Hold[<< ~/some_example/dir/] // FullForm
- = Hold[Get["~/some_example/dir/"]]
- #> Hold[<<`/.\-_:$*~?] // FullForm
- = Hold[Get["`/.\\\\-_:$*~?"]]
"""
operator = "<<"
options = {
@@ -528,29 +502,11 @@ class OpenRead(_OpenAction):
>> OpenRead["ExampleData/EinsteinSzilLetter.txt", CharacterEncoding->"UTF8"]
= InputStream[...]
- #> Close[%];
-
- S> Close[OpenRead["https://raw.githubusercontent.com/Mathics3/mathics-core/master/README.rst"]];
-
- #> OpenRead[]
- : OpenRead called with 0 arguments; 1 argument is expected.
- = OpenRead[]
- #> OpenRead[y]
- : File specification y is not a string of one or more characters.
- = OpenRead[y]
+ The stream must be closed after using it to release the resource:
+ >> Close[%];
- #> OpenRead[""]
- : File specification is not a string of one or more characters.
- = OpenRead[]
-
- #> OpenRead["MathicsNonExampleFile"]
- : Cannot open MathicsNonExampleFile.
- = OpenRead[MathicsNonExampleFile]
-
- #> OpenRead["ExampleData/EinsteinSzilLetter.txt", BinaryFormat -> True, CharacterEncoding->"UTF8"]
- = InputStream[...]
- #> Close[%];
+ S> Close[OpenRead["https://raw.githubusercontent.com/Mathics3/mathics-core/master/README.rst"]];
"""
summary_text = "open a file for reading"
@@ -569,11 +525,7 @@ class OpenWrite(_OpenAction):
>> OpenWrite[]
= OutputStream[...]
- #> DeleteFile[Close[%]];
-
- #> OpenWrite[BinaryFormat -> True]
- = OutputStream[...]
- #> DeleteFile[Close[%]];
+ >> DeleteFile[Close[%]];
"""
summary_text = (
@@ -594,14 +546,8 @@ class OpenAppend(_OpenAction):
>> OpenAppend[]
= OutputStream[...]
- #> DeleteFile[Close[%]];
+ >> DeleteFile[Close[%]];
- #> appendFile = OpenAppend["MathicsNonExampleFile"]
- = OutputStream[MathicsNonExampleFile, ...]
-
- #> Close[appendFile]
- = MathicsNonExampleFile
- #> DeleteFile["MathicsNonExampleFile"]
"""
mode = "a"
@@ -757,17 +703,7 @@ class PutAppend(BinaryOperator):
| 265252859812191058636308480000000
| 8320987112741390144276341183223364380754172606361245952449277696409600000000000000
| "string"
- #> DeleteFile["factorials"];
-
- ## writing to dir
- #> x >>> /var/
- : Cannot open /var/.
- = x >>> /var/
-
- ## writing to read only file
- #> x >>> /proc/uptime
- : Cannot open /proc/uptime.
- = x >>> /proc/uptime
+ >> DeleteFile["factorials"];
"""
operator = ">>>"
@@ -842,20 +778,12 @@ class Read(Builtin):
Word
- ## Malformed InputString
- #> Read[InputStream[String], {Word, Number}]
- = Read[InputStream[String], {Word, Number}]
-
- ## Correctly formed InputString but not open
- #> Read[InputStream[String, -1], {Word, Number}]
- : InputStream[String, -1] is not open.
- = Read[InputStream[String, -1], {Word, Number}]
## Reading Strings
>> stream = StringToStream["abc123"];
>> Read[stream, String]
= abc123
- #> Read[stream, String]
+ >> Read[stream, String]
= EndOfFile
#> Close[stream];
@@ -865,60 +793,19 @@ class Read(Builtin):
= abc
>> Read[stream, Word]
= 123
- #> Read[stream, Word]
- = EndOfFile
- #> Close[stream];
- #> stream = StringToStream[""];
- #> Read[stream, Word]
- = EndOfFile
- #> Read[stream, Word]
+ >> Read[stream, Word]
= EndOfFile
#> Close[stream];
-
## Number
>> stream = StringToStream["123, 4"];
>> Read[stream, Number]
= 123
>> Read[stream, Number]
= 4
- #> Read[stream, Number]
+ >> Read[stream, Number]
= EndOfFile
#> Close[stream];
- #> stream = StringToStream["123xyz 321"];
- #> Read[stream, Number]
- = 123
- #> Quiet[Read[stream, Number]]
- = $Failed
-
- ## Real
- #> stream = StringToStream["123, 4abc"];
- #> Read[stream, Real]
- = 123.
- #> Read[stream, Real]
- = 4.
- #> Quiet[Read[stream, Number]]
- = $Failed
- #> Close[stream];
- #> stream = StringToStream["1.523E-19"]; Read[stream, Real]
- = 1.523×10^-19
- #> Close[stream];
- #> stream = StringToStream["-1.523e19"]; Read[stream, Real]
- = -1.523×10^19
- #> Close[stream];
- #> stream = StringToStream["3*^10"]; Read[stream, Real]
- = 3.×10^10
- #> Close[stream];
- #> stream = StringToStream["3.*^10"]; Read[stream, Real]
- = 3.×10^10
- #> Close[stream];
-
- ## Expression
- #> stream = StringToStream["x + y Sin[z]"]; Read[stream, Expression]
- = x + y Sin[z]
- #> Close[stream];
- ## #> stream = Quiet[StringToStream["Sin[1 123"]; Read[stream, Expression]]
- ## = $Failed
## HoldExpression:
>> stream = StringToStream["2+2\\n2+3"];
@@ -930,7 +817,7 @@ class Read(Builtin):
>> Read[stream, Expression]
= 5
- >> Close[stream];
+ #> Close[stream];
Reading a comment however will return the empty list:
>> stream = StringToStream["(* ::Package:: *)"];
@@ -938,28 +825,16 @@ class Read(Builtin):
>> Read[stream, Hold[Expression]]
= {}
- >> Close[stream];
+ #> Close[stream];
## Multiple types
>> stream = StringToStream["123 abc"];
>> Read[stream, {Number, Word}]
= {123, abc}
- #> Read[stream, {Number, Word}]
+ >> Read[stream, {Number, Word}]
= EndOfFile
- #> lose[stream];
-
- #> stream = StringToStream["123 abc"];
- #> Quiet[Read[stream, {Word, Number}]]
- = $Failed
- #> Close[stream];
-
- #> stream = StringToStream["123 123"]; Read[stream, {Real, Number}]
- = {123., 123}
#> Close[stream];
- #> Quiet[Read[stream, {Real}]]
- = Read[InputStream[String, ...], {Real}]
-
Multiple lines:
>> stream = StringToStream["\\"Tengo una\\nvaca lechera.\\""]; Read[stream]
= Tengo una
@@ -1232,15 +1107,7 @@ class ReadList(Read):
= {abc123}
>> InputForm[%]
= {"abc123"}
-
- #> ReadList[stream, "Invalid"]
- : Invalid is not a valid format specification.
- = ReadList[..., Invalid]
#> Close[stream];
-
-
- #> ReadList[StringToStream["a 1 b 2"], {Word, Number}, 1]
- = {{a, 1}}
"""
# TODO
@@ -1398,10 +1265,6 @@ class SetStreamPosition(Builtin):
>> Read[stream, Word]
= is
- #> SetStreamPosition[stream, -5]
- : Invalid I/O Seek.
- = 10
-
>> SetStreamPosition[stream, Infinity]
= 16
"""
@@ -1490,7 +1353,7 @@ class Skip(Read):
>> Skip[stream, Word, 2]
>> Read[stream, Word]
= d
- #> Skip[stream, Word]
+ >> Skip[stream, Word]
= EndOfFile
#> Close[stream];
"""
@@ -1555,7 +1418,7 @@ class Find(Read):
= in manuscript, leads me to expect that the element uranium may be turned into
>> Find[stream, "uranium"]
= become possible to set up a nuclear chain reaction in a large mass of uranium,
- >> Close[stream]
+ #> Close[stream]
= ...
>> stream = OpenRead["ExampleData/EinsteinSzilLetter.txt", CharacterEncoding->"UTF8"];
@@ -1563,7 +1426,7 @@ class Find(Read):
= a new and important source of energy in the immediate future. Certain aspects
>> Find[stream, {"energy", "power"} ]
= by which vast amounts of power and large quantities of new radium-like
- >> Close[stream]
+ #> Close[stream]
= ...
"""
@@ -1649,14 +1512,8 @@ class StringToStream(Builtin):
>> strm = StringToStream["abc 123"]
= InputStream[String, ...]
- #> Read[strm, Word]
- = abc
-
- #> Read[strm, Number]
- = 123
-
- #> Close[strm]
- = String
+ The stream must be closed after using it, to release the resource:
+ >> Close[strm];
"""
summary_text = "open an input stream for reading from a string"
@@ -1685,14 +1542,6 @@ class Streams(Builtin):
>> Streams["stdout"]
= ...
-
- #> OpenWrite[]
- = ...
- #> Streams[%[[1]]]
- = {OutputStream[...]}
-
- #> Streams["some_nonexistent_name"]
- = {}
"""
summary_text = "list currently open streams"
@@ -1764,11 +1613,12 @@ class Write(Builtin):
= ...
>> Write[stream, 10 x + 15 y ^ 2]
>> Write[stream, 3 Sin[z]]
+ The stream must be closed in order to use the file again:
>> Close[stream];
>> stream = OpenRead[%];
>> ReadList[stream]
= {10 x + 15 y ^ 2, 3 Sin[z]}
- #> DeleteFile[Close[stream]];
+ >> DeleteFile[Close[stream]];
"""
summary_text = "write a sequence of expressions to a stream, ending the output with a newline (line feed)"
@@ -1817,7 +1667,7 @@ class WriteString(Builtin):
>> FilePrint[%]
| This is a test 1This is also a test 2
- #> DeleteFile[pathname];
+ >> DeleteFile[pathname];
>> stream = OpenWrite[];
>> WriteString[stream, "This is a test 1", "This is also a test 2"]
>> pathname = Close[stream]
@@ -1825,29 +1675,7 @@ class WriteString(Builtin):
>> FilePrint[%]
| This is a test 1This is also a test 2
- #> DeleteFile[pathname];
- #> stream = OpenWrite[];
- #> WriteString[stream, 100, 1 + x + y, Sin[x + y]]
- #> pathname = Close[stream]
- = ...
- #> FilePrint[%]
- | 1001 + x + ySin[x + y]
-
- #> DeleteFile[pathname];
- #> stream = OpenWrite[];
- #> WriteString[stream]
- #> pathame = Close[stream]
- = ...
- #> FilePrint[%]
-
- #> WriteString[%%, abc]
- #> Streams[%%%][[1]]
- = ...
- #> pathname = Close[%];
- #> FilePrint[%]
- | abc
- #> DeleteFile[pathname];
- #> Clear[pathname];
+ >> DeleteFile[pathname];
If stream is the string "stdout" or "stderr", writes to the system standard output/ standard error channel:
diff --git a/mathics/builtin/files_io/filesystem.py b/mathics/builtin/files_io/filesystem.py
index edb9fdb3e..f0faf505e 100644
--- a/mathics/builtin/files_io/filesystem.py
+++ b/mathics/builtin/files_io/filesystem.py
@@ -53,9 +53,6 @@ class AbsoluteFileName(Builtin):
>> AbsoluteFileName["ExampleData/sunflowers.jpg"]
= ...
- #> AbsoluteFileName["Some/NonExistant/Path.ext"]
- : File not found during AbsoluteFileName[Some/NonExistant/Path.ext].
- = $Failed
"""
messages = {
@@ -363,23 +360,6 @@ class DirectoryName(Builtin):
>> DirectoryName["a/b/c", 2]
= a
-
- #> DirectoryName["a/b/c", 3] // InputForm
- = ""
- #> DirectoryName[""] // InputForm
- = ""
-
- #> DirectoryName["a/b/c", x]
- : Positive machine-sized integer expected at position 2 in DirectoryName[a/b/c, x].
- = DirectoryName[a/b/c, x]
-
- #> DirectoryName["a/b/c", -1]
- : Positive machine-sized integer expected at position 2 in DirectoryName[a/b/c, -1].
- = DirectoryName[a/b/c, -1]
-
- #> DirectoryName[x]
- : String expected at position 1 in DirectoryName[x].
- = DirectoryName[x]
"""
messages = {
@@ -508,12 +488,6 @@ class FileBaseName(Builtin):
>> FileBaseName["file.tar.gz"]
= file.tar
-
- #> FileBaseName["file."]
- = file
-
- #> FileBaseName["file"]
- = file
"""
options = {
@@ -627,11 +601,6 @@ class FileExtension(Builtin):
>> FileExtension["file.tar.gz"]
= gz
-
- #> FileExtension["file."]
- = #<--#
- #> FileExtension["file"]
- = #<--#
"""
options = {
@@ -660,9 +629,6 @@ class FileInformation(Builtin):
>> FileInformation["ExampleData/sunflowers.jpg"]
= {File -> ..., FileType -> File, ByteCount -> 142286, Date -> ...}
-
- #> FileInformation["ExampleData/missing_file.jpg"]
- = {}
"""
rules = {
@@ -688,9 +654,6 @@ class FindFile(Builtin):
>> FindFile["VectorAnalysis`VectorAnalysis`"]
= ...
-
- #> FindFile["SomeTypoPackage`"]
- = $Failed
"""
messages = {
@@ -938,97 +901,6 @@ class Needs(Builtin):
>> Needs["VectorAnalysis`"]
- #> Needs["VectorAnalysis`"]
-
- #> Needs["SomeFakePackageOrTypo`"]
- : Cannot open SomeFakePackageOrTypo`.
- : Context SomeFakePackageOrTypo` was not created when Needs was evaluated.
- = $Failed
-
- #> Needs["VectorAnalysis"]
- : Invalid context specified at position 1 in Needs[VectorAnalysis]. A context must consist of valid symbol names separated by and ending with `.
- = Needs[VectorAnalysis]
-
- ## --- VectorAnalysis ---
-
- #> Needs["VectorAnalysis`"]
-
- #> DotProduct[{1,2,3}, {4,5,6}]
- = 32
- #> DotProduct[{-1.4, 0.6, 0.2}, {0.1, 0.6, 1.7}]
- = 0.56
-
- #> CrossProduct[{1,2,3}, {4,5,6}]
- = {-3, 6, -3}
- #> CrossProduct[{-1.4, 0.6, 0.2}, {0.1, 0.6, 1.7}]
- = {0.9, 2.4, -0.9}
-
- #> ScalarTripleProduct[{-2,3,1},{0,4,0},{-1,3,3}]
- = -20
- #> ScalarTripleProduct[{-1.4,0.6,0.2}, {0.1,0.6,1.7}, {0.7,-1.5,-0.2}]
- = -2.79
-
- #> CoordinatesToCartesian[{2, Pi, 3}, Spherical]
- = {0, 0, -2}
- #> CoordinatesFromCartesian[%, Spherical]
- = {2, Pi, 0}
- #> CoordinatesToCartesian[{2, Pi, 3}, Cylindrical]
- = {-2, 0, 3}
- #> CoordinatesFromCartesian[%, Cylindrical]
- = {2, Pi, 3}
- ## Needs Sin/Cos exact value (PR #100) for these tests to pass
- ## #> CoordinatesToCartesian[{2, Pi / 4, Pi / 3}, Spherical]
- ## = {Sqrt[2] / 2, Sqrt[6] / 2, Sqrt[2]}
- ## #> CoordinatesFromCartesian[%, Spherical]
- ## = {2, Pi / 4, Pi / 3}
- ## #> CoordinatesToCartesian[{2, Pi / 4, -1}, Cylindrical]
- ## = {Sqrt[2], Sqrt[2], -1}
- ## #> CoordinatesFromCartesian[%, Cylindrical]
- ## = {2, Pi / 4, -1}
- #> CoordinatesToCartesian[{0.27, 0.51, 0.92}, Cylindrical]
- = {0.235641, 0.131808, 0.92}
- #> CoordinatesToCartesian[{0.27, 0.51, 0.92}, Spherical]
- = {0.0798519, 0.104867, 0.235641}
-
- #> Coordinates[]
- = {Xx, Yy, Zz}
- #> Coordinates[Spherical]
- = {Rr, Ttheta, Pphi}
- #> SetCoordinates[Cylindrical]
- = Cylindrical[Rr, Ttheta, Zz]
- #> Coordinates[]
- = {Rr, Ttheta, Zz}
- #> CoordinateSystem
- = Cylindrical
- #> Parameters[]
- = {}
- #> CoordinateRanges[]
- ## = {0 <= Rr < Infinity, -Pi < Ttheta <= Pi, -Infinity < Zz < Infinity}
- = {0 <= Rr && Rr < Infinity, -Pi < Ttheta && Ttheta <= Pi, -Infinity < Zz < Infinity}
- #> CoordinateRanges[Cartesian]
- = {-Infinity < Xx < Infinity, -Infinity < Yy < Infinity, -Infinity < Zz < Infinity}
- #> ScaleFactors[Cartesian]
- = {1, 1, 1}
- #> ScaleFactors[Spherical]
- = {1, Rr, Rr Sin[Ttheta]}
- #> ScaleFactors[Cylindrical]
- = {1, Rr, 1}
- #> ScaleFactors[{2, 1, 3}, Cylindrical]
- = {1, 2, 1}
- #> JacobianDeterminant[Cartesian]
- = 1
- #> JacobianDeterminant[Spherical]
- = Rr ^ 2 Sin[Ttheta]
- #> JacobianDeterminant[Cylindrical]
- = Rr
- #> JacobianDeterminant[{2, 1, 3}, Cylindrical]
- = 2
- #> JacobianMatrix[Cartesian]
- = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}
- #> JacobianMatrix[Spherical]
- = {{Cos[Pphi] Sin[Ttheta], Rr Cos[Pphi] Cos[Ttheta], -Rr Sin[Pphi] Sin[Ttheta]}, {Sin[Pphi] Sin[Ttheta], Rr Cos[Ttheta] Sin[Pphi], Rr Cos[Pphi] Sin[Ttheta]}, {Cos[Ttheta], -Rr Sin[Ttheta], 0}}
- #> JacobianMatrix[Cylindrical]
- = {{Cos[Ttheta], -Rr Sin[Ttheta], 0}, {Sin[Ttheta], Rr Cos[Ttheta], 0}, {0, 0, 1}}
"""
messages = {
@@ -1223,10 +1095,6 @@ class SetDirectory(Builtin):
S> SetDirectory[]
= ...
-
- #> SetDirectory["MathicsNonExample"]
- : Cannot set current directory to MathicsNonExample.
- = $Failed
"""
messages = {
diff --git a/mathics/builtin/files_io/importexport.py b/mathics/builtin/files_io/importexport.py
index 42a147eb9..01e2b8ac0 100644
--- a/mathics/builtin/files_io/importexport.py
+++ b/mathics/builtin/files_io/importexport.py
@@ -1197,7 +1197,7 @@ class RegisterExport(Builtin):
>> FilePrint["sample.txt"]
| Encode this string!
- #> DeleteFile["sample.txt"]
+ >> DeleteFile["sample.txt"]
Very basic encrypted text exporter:
>> ExampleExporter2[filename_, data_, opts___] := Module[{strm = OpenWrite[filename], char}, (* TODO: Check data *) char = FromCharacterCode[Mod[ToCharacterCode[data] - 84, 26] + 97]; WriteString[strm, char]; Close[strm]]
@@ -1209,7 +1209,7 @@ class RegisterExport(Builtin):
>> FilePrint["sample.txt"]
| rapbqrguvffgevat
- #> DeleteFile["sample.txt"]
+ >> DeleteFile["sample.txt"]
"""
summary_text = "register an exporter for a file format"
@@ -1247,13 +1247,6 @@ class URLFetch(Builtin):
'URLFetch[$URL$]'
Returns the content of $URL$ as a string.
-
-
- #> Quiet[URLFetch["https:////", {}]]
- = $Failed
-
- ##> Quiet[URLFetch["https://www.example.com", {}]]
- # = ...
"""
summary_text = "fetch data from a URL"
@@ -1340,38 +1333,16 @@ class Import(Builtin):
imports from a URL.
- #> Import["ExampleData/ExampleData.tx"]
- : File not found during Import.
- = $Failed
- #> Import[x]
- : First argument x is not a valid file, directory, or URL specification.
- = $Failed
-
- ## CSV
- #> Import["ExampleData/numberdata.csv", "Elements"]
- = {Data, Grid}
- #> Import["ExampleData/numberdata.csv", "Data"]
- = {{0.88, 0.60, 0.94}, {0.76, 0.19, 0.51}, {0.97, 0.04, 0.26}, {0.33, 0.74, 0.79}, {0.42, 0.64, 0.56}}
- #> Import["ExampleData/numberdata.csv"]
- = {{0.88, 0.60, 0.94}, {0.76, 0.19, 0.51}, {0.97, 0.04, 0.26}, {0.33, 0.74, 0.79}, {0.42, 0.64, 0.56}}
- #> Import["ExampleData/numberdata.csv", "FieldSeparators" -> "."]
- = {{0, 88,0, 60,0, 94}, {0, 76,0, 19,0, 51}, {0, 97,0, 04,0, 26}, {0, 33,0, 74,0, 79}, {0, 42,0, 64,0, 56}}
## Text
>> Import["ExampleData/ExampleData.txt", "Elements"]
= {Data, Lines, Plaintext, String, Words}
>> Import["ExampleData/ExampleData.txt", "Lines"]
= ...
- #> Import["ExampleData/Middlemarch.txt"];
- : An invalid unicode sequence was encountered and ignored.
## JSON
>> Import["ExampleData/colors.json"]
= {colorsArray -> {{colorName -> black, rgbValue -> (0, 0, 0), hexValue -> #000000}, {colorName -> red, rgbValue -> (255, 0, 0), hexValue -> #FF0000}, {colorName -> green, rgbValue -> (0, 255, 0), hexValue -> #00FF00}, {colorName -> blue, rgbValue -> (0, 0, 255), hexValue -> #0000FF}, {colorName -> yellow, rgbValue -> (255, 255, 0), hexValue -> #FFFF00}, {colorName -> cyan, rgbValue -> (0, 255, 255), hexValue -> #00FFFF}, {colorName -> magenta, rgbValue -> (255, 0, 255), hexValue -> #FF00FF}, {colorName -> white, rgbValue -> (255, 255, 255), hexValue -> #FFFFFF}}}
-
- ## XML
- #> Import["ExampleData/InventionNo1.xml", "Tags"]
- = {accidental, alter, arpeggiate, ..., words}
"""
messages = {
@@ -1632,26 +1603,6 @@ class ImportString(Import):
attempts to determine the format of the string from its content.
-
- #> ImportString[x]
- : First argument x is not a string.
- = $Failed
-
- ## CSV
- #> datastring = "0.88, 0.60, 0.94\\n.076, 0.19, .51\\n0.97, 0.04, .26";
- #> ImportString[datastring, "Elements"]
- = {Data, Lines, Plaintext, String, Words}
- #> ImportString[datastring, {"CSV","Elements"}]
- = {Data, Grid}
- #> ImportString[datastring, {"CSV", "Data"}]
- = {{0.88, 0.60, 0.94}, {.076, 0.19, .51}, {0.97, 0.04, .26}}
- #> ImportString[datastring]
- = 0.88, 0.60, 0.94
- . .076, 0.19, .51
- . 0.97, 0.04, .26
- #> ImportString[datastring, "CSV","FieldSeparators" -> "."]
- = {{0, 88, 0, 60, 0, 94}, {076, 0, 19, , 51}, {0, 97, 0, 04, , 26}}
-
## Text
>> str = "Hello!\\n This is a testing text\\n";
>> ImportString[str, "Elements"]
@@ -1736,49 +1687,6 @@ class Export(Builtin):
'Export["$file$", $exprs$, $elems$]'
exports $exprs$ to a file as elements specified by $elems$.
-
- ## Invalid Filename
- #> Export["abc.", 1+2]
- : Cannot infer format of file abc..
- = $Failed
- #> Export[".ext", 1+2]
- : Cannot infer format of file .ext.
- = $Failed
- #> Export[x, 1+2]
- : First argument x is not a valid file specification.
- = $Failed
-
- ## Explicit Format
- #> Export["abc.txt", 1+x, "JPF"]
- : {JPF} is not a valid set of export elements for the Text format.
- = $Failed
- #> Export["abc.txt", 1+x, {"JPF"}]
- : {JPF} is not a valid set of export elements for the Text format.
- = $Failed
-
- ## Empty elems
- #> Export["123.txt", 1+x, {}]
- = 123.txt
- #> Export["123.jcp", 1+x, {}]
- : Cannot infer format of file 123.jcp.
- = $Failed
-
- ## Compression
- ## #> Export["abc.txt", 1+x, "ZIP"] (* MMA Bug - Export::type *)
- ## : {ZIP} is not a valid set of export elements for the Text format.
- ## = $Failed
- ## #> Export["abc.txt", 1+x, "BZIP"] (* MMA Bug - General::stop *)
- ## : {BZIP} is not a valid set of export elements for the Text format.
- ## = $Failed
- ## #> Export["abc.txt", 1+x, {"BZIP", "ZIP", "Text"}]
- ## = abc.txt
- ## #> Export["abc.txt", 1+x, {"GZIP", "Text"}]
- ## = abc.txt
- ## #> Export["abc.txt", 1+x, {"BZIP2", "Text"}]
- ## = abc.txt
-
- ## FORMATS
-
"""
messages = {
@@ -2146,43 +2054,6 @@ class FileFormat(Builtin):
>> FileFormat["ExampleData/hedy.tif"]
= TIFF
-
- ## ASCII text
- #> FileFormat["ExampleData/BloodToilTearsSweat.txt"]
- = Text
- #> FileFormat["ExampleData/MadTeaParty.gif"]
- = GIF
- #> FileFormat["ExampleData/moon.tif"]
- = TIFF
-
- #> FileFormat["ExampleData/numberdata.csv"]
- = CSV
-
- #> FileFormat["ExampleData/EinsteinSzilLetter.txt"]
- = Text
-
- #> FileFormat["ExampleData/BloodToilTearsSweat.txt"]
- = Text
-
- ## Doesn't work on Microsoft Windows
- ## S> FileFormat["ExampleData/benzene.xyz"]
- ## = XYZ
-
- #> FileFormat["ExampleData/colors.json"]
- = JSON
-
- #> FileFormat["ExampleData/some-typo.extension"]
- : File not found during FileFormat[ExampleData/some-typo.extension].
- = $Failed
-
- #> FileFormat["ExampleData/Testosterone.svg"]
- = SVG
-
- #> FileFormat["ExampleData/colors.json"]
- = JSON
-
- #> FileFormat["ExampleData/InventionNo1.xml"]
- = XML
"""
summary_text = "determine the file format of a file"
diff --git a/mathics/builtin/intfns/combinatorial.py b/mathics/builtin/intfns/combinatorial.py
index 681f9277d..22a77f486 100644
--- a/mathics/builtin/intfns/combinatorial.py
+++ b/mathics/builtin/intfns/combinatorial.py
@@ -113,10 +113,6 @@ class Binomial(MPMathFunction):
= 0
>> Binomial[-10.5, -3.5]
= 0.
-
- ## TODO should be ComplexInfinity but mpmath returns +inf
- #> Binomial[-10, -3.5]
- = Infinity
"""
attributes = A_LISTABLE | A_NUMERIC_FUNCTION | A_PROTECTED
@@ -411,90 +407,10 @@ class Subsets(Builtin):
The odd-numbered subsets of {a,b,c,d} in reverse order:
>> Subsets[{a, b, c, d}, All, {15, 1, -2}]
= {{b, c, d}, {a, b, d}, {c, d}, {b, c}, {a, c}, {d}, {b}, {}}
-
- #> Subsets[{}]
- = {{}}
-
- #> Subsets[]
- = Subsets[]
-
- #> Subsets[{a, b, c}, 2.5]
- : Position 2 of Subsets[{a, b, c}, 2.5] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer
- = Subsets[{a, b, c}, 2.5]
-
- #> Subsets[{a, b, c}, -1]
- : Position 2 of Subsets[{a, b, c}, -1] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer
- = Subsets[{a, b, c}, -1]
-
- #> Subsets[{a, b, c}, {3, 4, 5, 6}]
- : Position 2 of Subsets[{a, b, c}, {3, 4, 5, 6}] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer
- = Subsets[{a, b, c}, {3, 4, 5, 6}]
-
- #> Subsets[{a, b, c}, {-1, 2}]
- : Position 2 of Subsets[{a, b, c}, {-1, 2}] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer
- = Subsets[{a, b, c}, {-1, 2}]
-
- #> Subsets[{a, b, c}, All]
- = {{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}}
-
- #> Subsets[{a, b, c}, Infinity]
- = {{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}}
-
- #> Subsets[{a, b, c}, ALL]
- : Position 2 of Subsets[{a, b, c}, ALL] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer
- = Subsets[{a, b, c}, ALL]
-
- #> Subsets[{a, b, c}, {a}]
- : Position 2 of Subsets[{a, b, c}, {a}] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer
- = Subsets[{a, b, c}, {a}]
-
- #> Subsets[{a, b, c}, {}]
- : Position 2 of Subsets[{a, b, c}, {}] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer
- = Subsets[{a, b, c}, {}]
-
- #> Subsets[{a, b}, 0]
- = {{}}
-
- #> Subsets[{1, 2}, x]
- : Position 2 of Subsets[{1, 2}, x] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer
- = Subsets[{1, 2}, x]
-
- #> Subsets[x]
- : Nonatomic expression expected at position 1 in Subsets[x].
- = Subsets[x]
-
- #> Subsets[x, {1, 2}]
- : Nonatomic expression expected at position 1 in Subsets[x, {1, 2}].
- = Subsets[x, {1, 2}]
-
- #> Subsets[x, {1, 2, 3}, {1, 3}]
- : Nonatomic expression expected at position 1 in Subsets[x, {1, 2, 3}, {1, 3}].
- = Subsets[x, {1, 2, 3}, {1, 3}]
-
- #> Subsets[a + b + c]
- = {0, a, b, c, a + b, a + c, b + c, a + b + c}
-
- #> Subsets[f[a, b, c]]
- = {f[], f[a], f[b], f[c], f[a, b], f[a, c], f[b, c], f[a, b, c]}
-
- #> Subsets[a + b + c, {1, 3, 2}]
- = {a, b, c, a + b + c}
-
- #> Subsets[a* b * c, All, {6}]
- = {a c}
-
- #> Subsets[{a, b, c}, {1, Infinity}]
- = {{a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}}
-
- #> Subsets[{a, b, c}, {1, Infinity, 2}]
- = {{a}, {b}, {c}, {a, b, c}}
-
- #> Subsets[{a, b, c}, {3, Infinity, -1}]
- = {}
"""
messages = {
- "nninfseq": "Position 2 of `1` must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer",
+ "nninfseq": "Position 2 of `1` must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer.",
"normal": "Nonatomic expression expected at position 1 in `1`.",
}
diff --git a/mathics/builtin/intfns/divlike.py b/mathics/builtin/intfns/divlike.py
index 864558707..b68dfd5ea 100644
--- a/mathics/builtin/intfns/divlike.py
+++ b/mathics/builtin/intfns/divlike.py
@@ -298,16 +298,6 @@ class Quotient(Builtin):
>> Quotient[23, 7]
= 3
-
- #> Quotient[13, 0]
- : Infinite expression Quotient[13, 0] encountered.
- = ComplexInfinity
- #> Quotient[-17, 7]
- = -3
- #> Quotient[-17, -4]
- = 4
- #> Quotient[19, -4]
- = -5
"""
attributes = A_LISTABLE | A_NUMERIC_FUNCTION | A_PROTECTED
@@ -338,24 +328,6 @@ class QuotientRemainder(Builtin):
>> QuotientRemainder[23, 7]
= {3, 2}
-
- #> QuotientRemainder[13, 0]
- : The argument 0 in QuotientRemainder[13, 0] should be nonzero.
- = QuotientRemainder[13, 0]
- #> QuotientRemainder[-17, 7]
- = {-3, 4}
- #> QuotientRemainder[-17, -4]
- = {4, -1}
- #> QuotientRemainder[19, -4]
- = {-5, -1}
- #> QuotientRemainder[a, 0]
- = QuotientRemainder[a, 0]
- #> QuotientRemainder[a, b]
- = QuotientRemainder[a, b]
- #> QuotientRemainder[5.2,2.5]
- = {2, 0.2}
- #> QuotientRemainder[5, 2.]
- = {2, 1.}
"""
attributes = A_LISTABLE | A_NUMERIC_FUNCTION | A_PROTECTED
diff --git a/mathics/builtin/intfns/recurrence.py b/mathics/builtin/intfns/recurrence.py
index aaf544c36..c28637069 100644
--- a/mathics/builtin/intfns/recurrence.py
+++ b/mathics/builtin/intfns/recurrence.py
@@ -63,9 +63,6 @@ class HarmonicNumber(MPMathFunction):
>> HarmonicNumber[3.8]
= 2.03806
-
- #> HarmonicNumber[-1.5]
- = 0.613706
"""
rules = {
diff --git a/mathics/builtin/numbers/algebra.py b/mathics/builtin/numbers/algebra.py
index 9c21f7782..178d424ab 100644
--- a/mathics/builtin/numbers/algebra.py
+++ b/mathics/builtin/numbers/algebra.py
@@ -373,12 +373,6 @@ class Apart(Builtin):
But it does not touch other expressions:
>> Sin[1 / (x ^ 2 - y ^ 2)] // Apart
= Sin[1 / (x ^ 2 - y ^ 2)]
-
- #> Attributes[f] = {HoldAll}; Apart[f[x + x]]
- = f[x + x]
-
- #> Attributes[f] = {}; Apart[f[x + x]]
- = f[2 x]
"""
attributes = A_LISTABLE | A_PROTECTED
@@ -504,25 +498,9 @@ class Coefficient(Builtin):
>> Coefficient[a x^2 + b y^3 + c x + d y + 5, x, 0]
= 5 + b y ^ 3 + d y
- ## Errors:
- #> Coefficient[x + y + 3]
- : Coefficient called with 1 argument; 2 or 3 arguments are expected.
- = Coefficient[3 + x + y]
- #> Coefficient[x + y + 3, 5]
- : 5 is not a valid variable.
- = Coefficient[3 + x + y, 5]
-
- ## This is known bug of Sympy 1.0, next Sympy version will fix it by this commit
- ## https://github.com/sympy/sympy/commit/25bf64b64d4d9a2dc563022818d29d06bc740d47
- ## #> Coefficient[x * y, z, 0]
- ## = x y
- ## ## Sympy 1.0 retuns 0
-
## ## TODO: Support Modulus
## >> Coefficient[(x + 2)^3 + (x + 3)^2, x, 0, Modulus -> 3]
## = 2
- ## #> Coefficient[(x + 2)^3 + (x + 3)^2, x, 0, {Modulus -> 3, Modulus -> 2, Modulus -> 10}]
- ## = {2, 1, 7}
"""
attributes = A_LISTABLE | A_PROTECTED
@@ -910,21 +888,11 @@ class CoefficientList(Builtin):
= {2 / (-3 + y), 1 / (-3 + y) + 1 / (-2 + y)}
>> CoefficientList[(x + y)^3, z]
= {(x + y) ^ 3}
- #> CoefficientList[x + y, 5]
- : 5 is not a valid variable.
- = CoefficientList[x + y, 5]
-
## Form 2 CoefficientList[poly, {var1, var2, ...}]
>> CoefficientList[a x^2 + b y^3 + c x + d y + 5, {x, y}]
= {{5, d, 0, b}, {c, 0, 0, 0}, {a, 0, 0, 0}}
>> CoefficientList[(x - 2 y + 3 z)^3, {x, y, z}]
= {{{0, 0, 0, 27}, {0, 0, -54, 0}, {0, 36, 0, 0}, {-8, 0, 0, 0}}, {{0, 0, 27, 0}, {0, -36, 0, 0}, {12, 0, 0, 0}, {0, 0, 0, 0}}, {{0, 9, 0, 0}, {-6, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, {{1, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}}
- #> CoefficientList[(x - 2 y)^4, {x, 2}]
- : 2 is not a valid variable.
- = CoefficientList[(x - 2 y) ^ 4, {x, 2}]
- #> CoefficientList[x / y, {x, y}]
- : x / y is not a polynomial.
- = CoefficientList[x / y, {x, y}]
"""
messages = {
@@ -1182,22 +1150,6 @@ class Expand(_Expand):
>> Expand[(1 + a)^12, Modulus -> 4]
= 1 + 2 a ^ 2 + 3 a ^ 4 + 3 a ^ 8 + 2 a ^ 10 + a ^ 12
-
- #> Expand[x, Modulus -> -1] (* copy odd MMA behaviour *)
- = 0
- #> Expand[x, Modulus -> x]
- : Value of option Modulus -> x should be an integer.
- = Expand[x, Modulus -> x]
-
- #> a(b(c+d)+e) // Expand
- = a b c + a b d + a e
-
- #> (y^2)^(1/2)/(2x+2y)//Expand
- = Sqrt[y ^ 2] / (2 x + 2 y)
-
-
- #> 2(3+2x)^2/(5+x^2+3x)^3 // Expand
- = 24 x / (5 + 3 x + x ^ 2) ^ 3 + 8 x ^ 2 / (5 + 3 x + x ^ 2) ^ 3 + 18 / (5 + 3 x + x ^ 2) ^ 3
"""
summary_text = "expand out products and powers"
@@ -1303,15 +1255,6 @@ class ExpandDenominator(_Expand):
>> ExpandDenominator[(a + b) ^ 2 / ((c + d)^2 (e + f))]
= (a + b) ^ 2 / (c ^ 2 e + c ^ 2 f + 2 c d e + 2 c d f + d ^ 2 e + d ^ 2 f)
-
- ## Modulus option
- #> ExpandDenominator[1 / (x + y)^3, Modulus -> 3]
- = 1 / (x ^ 3 + y ^ 3)
- #> ExpandDenominator[1 / (x + y)^6, Modulus -> 4]
- = 1 / (x ^ 6 + 2 x ^ 5 y + 3 x ^ 4 y ^ 2 + 3 x ^ 2 y ^ 4 + 2 x y ^ 5 + y ^ 6)
-
- #> ExpandDenominator[2(3+2x)^2/(5+x^2+3x)^3]
- = 2 (3 + 2 x) ^ 2 / (125 + 225 x + 210 x ^ 2 + 117 x ^ 3 + 42 x ^ 4 + 9 x ^ 5 + x ^ 6)
"""
summary_text = "expand just the denominator of a rational expression"
@@ -1354,11 +1297,6 @@ class Exponent(Builtin):
= -Infinity
>> Exponent[1, x]
= 0
-
- ## errors:
- #> Exponent[x^2]
- : Exponent called with 1 argument; 2 or 3 arguments are expected.
- = Exponent[x ^ 2]
"""
attributes = A_LISTABLE | A_PROTECTED
@@ -1422,10 +1360,6 @@ class Factor(Builtin):
You can use Factor to find when a polynomial is zero:
>> x^2 - x == 0 // Factor
= x (-1 + x) == 0
-
- ## Issue659
- #> Factor[{x+x^2}]
- = {x (1 + x)}
"""
attributes = A_LISTABLE | A_PROTECTED
@@ -1467,9 +1401,6 @@ class FactorTermsList(Builtin):
= {2, -1 + x ^ 2}
>> FactorTermsList[x^2 - 2 x + 1]
= {1, 1 - 2 x + x ^ 2}
- #> FactorTermsList[2 x^2 - 2, x]
- = {2, 1, -1 + x ^ 2}
-
>> f = 3 (-1 + 2 x) (-1 + y) (1 - a)
= 3 (-1 + 2 x) (-1 + y) (1 - a)
>> FactorTermsList[f]
@@ -1775,17 +1706,6 @@ class MinimalPolynomial(Builtin):
= -2 - 2 x ^ 2 + x ^ 4
>> MinimalPolynomial[Sqrt[I + Sqrt[6]], x]
= 49 - 10 x ^ 4 + x ^ 8
-
- #> MinimalPolynomial[7a, x]
- : 7 a is not an explicit algebraic number.
- = MinimalPolynomial[7 a, x]
- #> MinimalPolynomial[3x^3 + 2x^2 + y^2 + ab, x]
- : ab + 2 x ^ 2 + 3 x ^ 3 + y ^ 2 is not an explicit algebraic number.
- = MinimalPolynomial[ab + 2 x ^ 2 + 3 x ^ 3 + y ^ 2, x]
-
- ## PurePoly
- #> MinimalPolynomial[Sqrt[2 + Sqrt[3]]]
- = 1 - 4 #1 ^ 2 + #1 ^ 4
"""
attributes = A_LISTABLE | A_PROTECTED
@@ -1874,37 +1794,6 @@ class PolynomialQ(Builtin):
= True
>> PolynomialQ[x^2 + axy^2 - bSin[c], {a, b, c}]
= False
-
- #> PolynomialQ[x, x, y]
- : PolynomialQ called with 3 arguments; 1 or 2 arguments are expected.
- = PolynomialQ[x, x, y]
-
- ## Always return True if argument is Null
- #> PolynomialQ[x^3 - 2 x/y + 3xz,]
- : Warning: comma encountered with no adjacent expression. The expression will be treated as Null (line 1 of "").
- = True
- #> PolynomialQ[, {x, y, z}]
- : Warning: comma encountered with no adjacent expression. The expression will be treated as Null (line 1 of "").
- = True
- #> PolynomialQ[, ]
- : Warning: comma encountered with no adjacent expression. The expression will be treated as Null (line 1 of "").
- : Warning: comma encountered with no adjacent expression. The expression will be treated as Null (line 1 of "").
- = True
-
- ## TODO: MMA and Sympy handle these cases differently
- ## #> PolynomialQ[x^(1/2) + 6xyz]
- ## : No variable is not supported in PolynomialQ.
- ## = True
- ## #> PolynomialQ[x^(1/2) + 6xyz, {}]
- ## : No variable is not supported in PolynomialQ.
- ## = True
-
- ## #> PolynomialQ[x^3 - 2 x/y + 3xz]
- ## : No variable is not supported in PolynomialQ.
- ## = False
- ## #> PolynomialQ[x^3 - 2 x/y + 3xz, {}]
- ## : No variable is not supported in PolynomialQ.
- ## = False
"""
messages = {
@@ -1994,9 +1883,6 @@ class Together(Builtin):
But it does not touch other functions:
>> Together[f[a / c + b / c]]
= f[a / c + b / c]
-
- #> f[x]/x+f[x]/x^2//Together
- = f[x] (1 + x) / x ^ 2
"""
attributes = A_LISTABLE | A_PROTECTED
@@ -2030,9 +1916,6 @@ class Variables(Builtin):
= {a, b, c, x, y}
>> Variables[x + Sin[y]]
= {x, Sin[y]}
- ## failing test case from MMA docs
- #> Variables[E^x]
- = {}
"""
summary_text = "list of variables in a polynomial"
diff --git a/mathics/builtin/numbers/calculus.py b/mathics/builtin/numbers/calculus.py
index ad5c38a1d..f6f39fd47 100644
--- a/mathics/builtin/numbers/calculus.py
+++ b/mathics/builtin/numbers/calculus.py
@@ -172,24 +172,6 @@ class D(SympyFunction):
Hesse matrix:
>> D[Sin[x] * Cos[y], {{x,y}, 2}]
= {{-Cos[y] Sin[x], -Cos[x] Sin[y]}, {-Cos[x] Sin[y], -Cos[y] Sin[x]}}
-
- #> D[2/3 Cos[x] - 1/3 x Cos[x] Sin[x] ^ 2,x]//Expand
- = -2 x Cos[x] ^ 2 Sin[x] / 3 + x Sin[x] ^ 3 / 3 - 2 Sin[x] / 3 - Cos[x] Sin[x] ^ 2 / 3
-
- #> D[f[#1], {#1,2}]
- = f''[#1]
- #> D[(#1&)[t],{t,4}]
- = 0
-
- #> Attributes[f] ={HoldAll}; Apart[f''[x + x]]
- = f''[2 x]
-
- #> Attributes[f] = {}; Apart[f''[x + x]]
- = f''[2 x]
-
- ## Issue #375
- #> D[{#^2}, #]
- = {2 #1}
"""
# TODO
@@ -416,16 +398,6 @@ class Derivative(PostfixOperator, SympyFunction):
= Derivative[2, 1][h]
>> Derivative[2, 0, 1, 0][h[g]]
= Derivative[2, 0, 1, 0][h[g]]
-
- ## Parser Tests
- #> Hold[f''] // FullForm
- = Hold[Derivative[2][f]]
- #> Hold[f ' '] // FullForm
- = Hold[Derivative[2][f]]
- #> Hold[f '' ''] // FullForm
- = Hold[Derivative[4][f]]
- #> Hold[Derivative[x][4] '] // FullForm
- = Hold[Derivative[1][Derivative[x][4]]]
"""
attributes = A_N_HOLD_ALL
@@ -866,12 +838,8 @@ class FindRoot(_BaseFinder):
= FindRoot[Sin[x] - x, {x, 0}]
- #> FindRoot[2.5==x,{x,0}]
- = {x -> 2.5}
-
>> FindRoot[x^2 - 2, {x, 1,3}, Method->"Secant"]
= {x -> 1.41421}
-
"""
rules = {
@@ -972,20 +940,6 @@ class Integrate(SympyFunction):
>> Integrate[f[x], {x, a, b}] // TeXForm
= \int_a^b f\left[x\right] \, dx
- #> DownValues[Integrate]
- = {}
- #> Definition[Integrate]
- = Attributes[Integrate] = {Protected, ReadProtected}
- .
- . Options[Integrate] = {Assumptions -> $Assumptions, GenerateConditions -> Automatic, PrincipalValue -> False}
- #> Integrate[Hold[x + x], {x, a, b}]
- = Integrate[Hold[x + x], {x, a, b}]
- #> Integrate[sin[x], x]
- = Integrate[sin[x], x]
-
- #> Integrate[x ^ 3.5 + x, x]
- = x ^ 2 / 2 + 0.222222 x ^ 4.5
-
Sometimes there is a loss of precision during integration.
You can check the precision of your result with the following sequence
of commands.
@@ -994,20 +948,6 @@ class Integrate(SympyFunction):
>> % // Precision
= MachinePrecision
- #> Integrate[1/(x^5+1), x]
- = RootSum[1 + 5 #1 + 25 #1 ^ 2 + 125 #1 ^ 3 + 625 #1 ^ 4&, Log[x + 5 #1] #1&] + Log[1 + x] / 5
-
- #> Integrate[ArcTan(x), x]
- = x ^ 2 ArcTan / 2
- #> Integrate[E[x], x]
- = Integrate[E[x], x]
-
- #> Integrate[Exp[-(x/2)^2],{x,-Infinity,+Infinity}]
- = 2 Sqrt[Pi]
-
- #> Integrate[Exp[-1/(x^2)], x]
- = x E ^ (-1 / x ^ 2) + Sqrt[Pi] Erf[1 / x]
-
>> Integrate[ArcSin[x / 3], x]
= x ArcSin[x / 3] + Sqrt[9 - x ^ 2]
diff --git a/mathics/builtin/numbers/diffeqns.py b/mathics/builtin/numbers/diffeqns.py
index 383e5322a..9224d81d7 100644
--- a/mathics/builtin/numbers/diffeqns.py
+++ b/mathics/builtin/numbers/diffeqns.py
@@ -42,48 +42,6 @@ class DSolve(Builtin):
>> DSolve[D[y[x, t], t] + 2 D[y[x, t], x] == 0, y[x, t], {x, t}]
= {{y[x, t] -> C[1][x - 2 t]}}
-
- ## FIXME: sympy solves this as `Function[{x}, C[1] + Integrate[ArcSin[f[2 x]], x]]`
- ## #> Attributes[f] = {HoldAll};
- ## #> DSolve[f[x + x] == Sin[f'[x]], f, x]
- ## : To avoid possible ambiguity, the arguments of the dependent variable in f[x + x] == Sin[f'[x]] should literally match the independent variables.
- ## = DSolve[f[x + x] == Sin[f'[x]], f, x]
-
- ## #> Attributes[f] = {};
- ## #> DSolve[f[x + x] == Sin[f'[x]], f, x]
- ## : To avoid possible ambiguity, the arguments of the dependent variable in f[2 x] == Sin[f'[x]] should literally match the independent variables.
- ## = DSolve[f[2 x] == Sin[f'[x]], f, x]
-
- #> DSolve[f'[x] == f[x], f, x] // FullForm
- = {{Rule[f, Function[{x}, Times[C[1], Power[E, x]]]]}}
-
- #> DSolve[f'[x] == f[x], f, x] /. {C[1] -> 1}
- = {{f -> (Function[{x}, 1 E ^ x])}}
-
- #> DSolve[f'[x] == f[x], f, x] /. {C -> D}
- = {{f -> (Function[{x}, D[1] E ^ x])}}
-
- #> DSolve[f'[x] == f[x], f, x] /. {C[1] -> C[0]}
- = {{f -> (Function[{x}, C[0] E ^ x])}}
-
- #> DSolve[f[x] == 0, f, {}]
- : {} cannot be used as a variable.
- = DSolve[f[x] == 0, f, {}]
-
- ## Order of arguments shoudn't matter
- #> DSolve[D[f[x, y], x] == D[f[x, y], y], f, {x, y}]
- = {{f -> (Function[{x, y}, C[1][-x - y]])}}
- #> DSolve[D[f[x, y], x] == D[f[x, y], y], f[x, y], {x, y}]
- = {{f[x, y] -> C[1][-x - y]}}
- #> DSolve[D[f[x, y], x] == D[f[x, y], y], f[x, y], {y, x}]
- = {{f[x, y] -> C[1][-x - y]}}
- """
-
- # XXX sympy #11669 test
- """
- #> DSolve[\\[Gamma]'[x] == 0, \\[Gamma], x]
- : Hit sympy bug #11669.
- = ...
"""
# TODO: GeneratedParameters option
diff --git a/mathics/builtin/numbers/exp.py b/mathics/builtin/numbers/exp.py
index e4c626e65..7156ef212 100644
--- a/mathics/builtin/numbers/exp.py
+++ b/mathics/builtin/numbers/exp.py
@@ -176,9 +176,6 @@ class Exp(MPMathFunction):
>> Plot[Exp[x], {x, 0, 3}]
= -Graphics-
- #> Exp[1.*^20]
- : Overflow occurred in computation.
- = Overflow[]
"""
rules = {
@@ -206,21 +203,6 @@ class Log(MPMathFunction):
= Indeterminate
>> Plot[Log[x], {x, 0, 5}]
= -Graphics-
-
- #> Log[1000] / Log[10] // Simplify
- = 3
-
- #> Log[1.4]
- = 0.336472
-
- #> Log[Exp[1.4]]
- = 1.4
-
- #> Log[-1.4]
- = 0.336472 + 3.14159 I
-
- #> N[Log[10], 30]
- = 2.30258509299404568401799145468
"""
summary_text = "logarithm function"
@@ -316,9 +298,6 @@ class LogisticSigmoid(Builtin):
>> LogisticSigmoid[{-0.2, 0.1, 0.3}]
= {0.450166, 0.524979, 0.574443}
-
- #> LogisticSigmoid[I Pi]
- = LogisticSigmoid[I Pi]
"""
summary_text = "logistic function"
diff --git a/mathics/builtin/numbers/hyperbolic.py b/mathics/builtin/numbers/hyperbolic.py
index 8f999077e..9884e619c 100644
--- a/mathics/builtin/numbers/hyperbolic.py
+++ b/mathics/builtin/numbers/hyperbolic.py
@@ -52,8 +52,6 @@ class ArcCosh(MPMathFunction):
= 0. + 1.5708 I
>> ArcCosh[0.00000000000000000000000000000000000000]
= 1.5707963267948966192313216916397514421 I
- #> ArcCosh[1.4]
- = 0.867015
"""
mpmath_name = "acosh"
@@ -94,9 +92,6 @@ class ArcCoth(MPMathFunction):
= 0. + 1.5708 I
>> ArcCoth[0.5]
= 0.549306 - 1.5708 I
-
- #> ArcCoth[0.000000000000000000000000000000000000000]
- = 1.57079632679489661923132169163975144210 I
"""
summary_text = "inverse hyperbolic cotangent function"
diff --git a/mathics/builtin/numbers/integer.py b/mathics/builtin/numbers/integer.py
index e2a4c0714..0d9ce034d 100644
--- a/mathics/builtin/numbers/integer.py
+++ b/mathics/builtin/numbers/integer.py
@@ -256,10 +256,6 @@ class FromDigits(Builtin):
= 0
>> FromDigits[""]
= 0
-
- #> FromDigits[x]
- : The input must be a string of digits or a list.
- = FromDigits[x, 10]
"""
summary_text = "integer from a list of digits"
diff --git a/mathics/builtin/numbers/linalg.py b/mathics/builtin/numbers/linalg.py
index 1a9da9992..d670c4727 100644
--- a/mathics/builtin/numbers/linalg.py
+++ b/mathics/builtin/numbers/linalg.py
@@ -124,10 +124,6 @@ class Eigenvalues(Builtin):
>> Eigenvalues[{{7, 1}, {-4, 3}}]
= {5, 5}
-
- #> Eigenvalues[{{1, 0}, {0}}]
- : Argument {{1, 0}, {0}} at position 1 is not a non-empty rectangular matrix.
- = Eigenvalues[{{1, 0}, {0}}]
"""
messages = {
@@ -221,9 +217,6 @@ class Eigenvectors(Builtin):
>> Eigenvectors[{{0.1, 0.2}, {0.8, 0.5}}]
= ...
### = {{-0.355518, -1.15048}, {-0.62896, 0.777438}}
-
- #> Eigenvectors[{{-2, 1, -1}, {-3, 2, 1}, {-1, 1, 0}}]
- = {{1, 7, 3}, {1, 1, 0}, {0, 0, 0}}
"""
messages = {
@@ -365,18 +358,6 @@ class LeastSquares(Builtin):
>> LeastSquares[{{1, 1, 1}, {1, 1, 2}}, {1, 3}]
: Solving for underdetermined system not implemented.
= LeastSquares[{{1, 1, 1}, {1, 1, 2}}, {1, 3}]
-
- ## Inconsistent system - ideally we'd print a different message
- #> LeastSquares[{{1, 1, 1}, {1, 1, 1}}, {1, 0}]
- : Solving for underdetermined system not implemented.
- = LeastSquares[{{1, 1, 1}, {1, 1, 1}}, {1, 0}]
-
- #> LeastSquares[{1, {2}}, {1, 2}]
- : Argument {1, {2}} at position 1 is not a non-empty rectangular matrix.
- = LeastSquares[{1, {2}}, {1, 2}]
- #> LeastSquares[{{1, 2}, {3, 4}}, {1, {2}}]
- : Argument {1, {2}} at position 2 is not a non-empty rectangular matrix.
- = LeastSquares[{{1, 2}, {3, 4}}, {1, {2}}]
"""
messages = {
@@ -510,13 +491,6 @@ class LinearSolve(Builtin):
>> LinearSolve[{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, {1, -2, 3}]
: Linear equation encountered that has no solution.
= LinearSolve[{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, {1, -2, 3}]
-
- #> LinearSolve[{1, {2}}, {1, 2}]
- : Argument {1, {2}} at position 1 is not a non-empty rectangular matrix.
- = LinearSolve[{1, {2}}, {1, 2}]
- #> LinearSolve[{{1, 2}, {3, 4}}, {1, {2}}]
- : Argument {1, {2}} at position 2 is not a non-empty rectangular matrix.
- = LinearSolve[{{1, 2}, {3, 4}}, {1, {2}}]
"""
messages = {
@@ -582,13 +556,6 @@ class MatrixExp(Builtin):
>> MatrixExp[{{1.5, 0.5}, {0.5, 2.0}}]
= {{5.16266, 3.02952}, {3.02952, 8.19218}}
-
- #> MatrixExp[{{a, 0}, {0, b}}]
- = {{E ^ a, 0}, {0, E ^ b}}
-
- #> MatrixExp[{{1, 0}, {0}}]
- : Argument {{1, 0}, {0}} at position 1 is not a non-empty rectangular matrix.
- = MatrixExp[{{1, 0}, {0}}]
"""
messages = {
@@ -628,13 +595,6 @@ class MatrixPower(Builtin):
>> MatrixPower[{{1, 2}, {2, 5}}, -3]
= {{169, -70}, {-70, 29}}
-
- #> MatrixPower[{{0, x}, {0, 0}}, n]
- = MatrixPower[{{0, x}, {0, 0}}, n]
-
- #> MatrixPower[{{1, 0}, {0}}, 2]
- : Argument {{1, 0}, {0}} at position 1 is not a non-empty rectangular matrix.
- = MatrixPower[{{1, 0}, {0}}, 2]
"""
messages = {
@@ -681,10 +641,6 @@ class MatrixRank(Builtin):
= 3
>> MatrixRank[{{a, b}, {3 a, 3 b}}]
= 1
-
- #> MatrixRank[{{1, 0}, {0}}]
- : Argument {{1, 0}, {0}} at position 1 is not a non-empty rectangular matrix.
- = MatrixRank[{{1, 0}, {0}}]
"""
messages = {
@@ -721,10 +677,6 @@ class NullSpace(Builtin):
= {}
>> MatrixRank[A]
= 3
-
- #> NullSpace[{1, {2}}]
- : Argument {1, {2}} at position 1 is not a non-empty rectangular matrix.
- = NullSpace[{1, {2}}]
"""
messages = {
@@ -764,10 +716,6 @@ class PseudoInverse(Builtin):
>> PseudoInverse[{{1.0, 2.5}, {2.5, 1.0}}]
= {{-0.190476, 0.47619}, {0.47619, -0.190476}}
-
- #> PseudoInverse[{1, {2}}]
- : Argument {1, {2}} at position 1 is not a non-empty rectangular matrix.
- = PseudoInverse[{1, {2}}]
"""
messages = {
@@ -798,10 +746,6 @@ class QRDecomposition(Builtin):
>> QRDecomposition[{{1, 2}, {3, 4}, {5, 6}}]
= {{{Sqrt[35] / 35, 3 Sqrt[35] / 35, Sqrt[35] / 7}, {13 Sqrt[210] / 210, 2 Sqrt[210] / 105, -Sqrt[210] / 42}}, {{Sqrt[35], 44 Sqrt[35] / 35}, {0, 2 Sqrt[210] / 35}}}
-
- #> QRDecomposition[{1, {2}}]
- : Argument {1, {2}} at position 1 is not a non-empty rectangular matrix.
- = QRDecomposition[{1, {2}}]
"""
messages = {
@@ -844,10 +788,6 @@ class RowReduce(Builtin):
. 0 1 2
.
. 0 0 0
-
- #> RowReduce[{{1, 0}, {0}}]
- : Argument {{1, 0}, {0}} at position 1 is not a non-empty rectangular matrix.
- = RowReduce[{{1, 0}, {0}}]
"""
messages = {
@@ -881,15 +821,6 @@ class SingularValueDecomposition(Builtin):
>> SingularValueDecomposition[{{1.5, 2.0}, {2.5, 3.0}}]
= {{{0.538954, 0.842335}, {0.842335, -0.538954}}, {{4.63555, 0.}, {0., 0.107862}}, {{0.628678, 0.777666}, {-0.777666, 0.628678}}}
-
-
- #> SingularValueDecomposition[{{3/2, 2}, {5/2, 3}}]
- : Symbolic SVD is not implemented, performing numerically.
- = {{{0.538954, 0.842335}, {0.842335, -0.538954}}, {{4.63555, 0.}, {0., 0.107862}}, {{0.628678, 0.777666}, {-0.777666, 0.628678}}}
-
- #> SingularValueDecomposition[{1, {2}}]
- : Argument {1, {2}} at position 1 is not a non-empty rectangular matrix.
- = SingularValueDecomposition[{1, {2}}]
"""
# Sympy lacks symbolic SVD
diff --git a/mathics/builtin/numbers/numbertheory.py b/mathics/builtin/numbers/numbertheory.py
index 85687c3db..9e9972238 100644
--- a/mathics/builtin/numbers/numbertheory.py
+++ b/mathics/builtin/numbers/numbertheory.py
@@ -91,14 +91,6 @@ class Divisors(Builtin):
= {1, 2, 4, 8, 11, 16, 22, 32, 44, 64, 88, 176, 352, 704}
>> Divisors[{87, 106, 202, 305}]
= {{1, 3, 29, 87}, {1, 2, 53, 106}, {1, 2, 101, 202}, {1, 5, 61, 305}}
- #> Divisors[0]
- = Divisors[0]
- #> Divisors[{-206, -502, -1702, 9}]
- = {{1, 2, 103, 206}, {1, 2, 251, 502}, {1, 2, 23, 37, 46, 74, 851, 1702}, {1, 3, 9}}
- #> Length[Divisors[1000*369]]
- = 96
- #> Length[Divisors[305*176*369*100]]
- = 672
"""
# TODO: support GaussianIntegers
@@ -275,21 +267,6 @@ class FractionalPart(Builtin):
>> FractionalPart[-5.25]
= -0.25
-
- #> FractionalPart[b]
- = FractionalPart[b]
-
- #> FractionalPart[{-2.4, -2.5, -3.0}]
- = {-0.4, -0.5, 0.}
-
- #> FractionalPart[14/32]
- = 7 / 16
-
- #> FractionalPart[4/(1 + 3 I)]
- = 2 / 5 - I / 5
-
- #> FractionalPart[Pi^20]
- = -8769956796 + Pi ^ 20
"""
attributes = A_LISTABLE | A_NUMERIC_FUNCTION | A_READ_PROTECTED | A_PROTECTED
@@ -370,47 +347,6 @@ class MantissaExponent(Builtin):
>> MantissaExponent[10, b]
= MantissaExponent[10, b]
-
- #> MantissaExponent[E, Pi]
- = {E / Pi, 1}
-
- #> MantissaExponent[Pi, Pi]
- = {1 / Pi, 2}
-
- #> MantissaExponent[5/2 + 3, Pi]
- = {11 / (2 Pi ^ 2), 2}
-
- #> MantissaExponent[b]
- = MantissaExponent[b]
-
- #> MantissaExponent[17, E]
- = {17 / E ^ 3, 3}
-
- #> MantissaExponent[17., E]
- = {0.84638, 3}
-
- #> MantissaExponent[Exp[Pi], 2]
- = {E ^ Pi / 32, 5}
-
- #> MantissaExponent[3 + 2 I, 2]
- : The value 3 + 2 I is not a real number
- = MantissaExponent[3 + 2 I, 2]
-
- #> MantissaExponent[25, 0.4]
- : Base 0.4 is not a real number greater than 1.
- = MantissaExponent[25, 0.4]
-
- #> MantissaExponent[0.0000124]
- = {0.124, -4}
-
- #> MantissaExponent[0.0000124, 2]
- = {0.812646, -16}
-
- #> MantissaExponent[0]
- = {0, 0}
-
- #> MantissaExponent[0, 2]
- = {0, 0}
"""
attributes = A_LISTABLE | A_PROTECTED
@@ -674,9 +610,6 @@ class PrimePowerQ(Builtin):
>> PrimePowerQ[371293]
= True
-
- #> PrimePowerQ[1]
- = False
"""
attributes = A_LISTABLE | A_PROTECTED | A_READ_PROTECTED
@@ -687,19 +620,19 @@ class PrimePowerQ(Builtin):
# TODO: GaussianIntegers option
"""
- #> PrimePowerQ[5, GaussianIntegers -> True]
+ ##> PrimePowerQ[5, GaussianIntegers -> True]
= False
"""
# TODO: Complex args
"""
- #> PrimePowerQ[{3 + I, 3 - 2 I, 3 + 4 I, 9 + 7 I}]
+ ##> PrimePowerQ[{3 + I, 3 - 2 I, 3 + 4 I, 9 + 7 I}]
= {False, True, True, False}
"""
# TODO: Gaussian rationals
"""
- #> PrimePowerQ[2/125 - 11 I/125]
+ ##> PrimePowerQ[2/125 - 11 I/125]
= True
"""
@@ -740,12 +673,6 @@ class RandomPrime(Builtin):
>> RandomPrime[{10,30}, {2,5}]
= ...
-
- #> RandomPrime[{10,12}, {2,2}]
- = {{11, 11}, {11, 11}}
-
- #> RandomPrime[2, {3,2}]
- = {{2, 2}, {2, 2}, {2, 2}}
"""
messages = {
diff --git a/mathics/builtin/numbers/randomnumbers.py b/mathics/builtin/numbers/randomnumbers.py
index 580ce0c35..77910941e 100644
--- a/mathics/builtin/numbers/randomnumbers.py
+++ b/mathics/builtin/numbers/randomnumbers.py
@@ -334,25 +334,15 @@ class RandomComplex(Builtin):
>> RandomComplex[]
= ...
- #> 0 <= Re[%] <= 1 && 0 <= Im[%] <= 1
- = True
>> RandomComplex[{1+I, 5+5I}]
= ...
- #> 1 <= Re[%] <= 5 && 1 <= Im[%] <= 5
- = True
>> RandomComplex[1+I, 5]
= {..., ..., ..., ..., ...}
>> RandomComplex[{1+I, 2+2I}, {2, 2}]
= {{..., ...}, {..., ...}}
-
- #> RandomComplex[{6, 2 Pi + I}]
- = 6...
-
- #> RandomComplex[{6.3, 2.5 I}] // FullForm
- = Complex[..., ...]
"""
messages = {
@@ -463,8 +453,6 @@ class RandomInteger(Builtin):
>> RandomInteger[{1, 5}]
= ...
- #> 1 <= % <= 5
- = True
>> RandomInteger[100, {2, 3}] // TableForm
= ... ... ...
@@ -542,21 +530,8 @@ class RandomReal(Builtin):
>> RandomReal[]
= ...
- #> 0 <= % <= 1
- = True
-
>> RandomReal[{1, 5}]
= ...
-
- ## needs too much horizontal space in TeX form
- #> RandomReal[100, {2, 3}] // TableForm
- = ... ... ...
- .
- . ... ... ...
-
- #> RandomReal[{0, 1}, {1, -1}]
- : The array dimensions {1, -1} given in position 2 of RandomReal[{0, 1}, {1, -1}] should be a list of non-negative machine-sized integers giving the dimensions for the result.
- = RandomReal[{0, 1}, {1, -1}]
"""
messages = {
@@ -691,10 +666,6 @@ class SeedRandom(Builtin):
>> SeedRandom[]
>> RandomInteger[100]
= ...
-
- #> SeedRandom[x]
- : Argument x should be an integer or string.
- = SeedRandom[x]
"""
messages = {
diff --git a/mathics/builtin/numbers/trig.py b/mathics/builtin/numbers/trig.py
index 1218ae2b7..8ea925163 100644
--- a/mathics/builtin/numbers/trig.py
+++ b/mathics/builtin/numbers/trig.py
@@ -550,21 +550,6 @@ class ArcTan(MPMathFunction):
>> ArcTan[1, 1]
= Pi / 4
- #> ArcTan[-1, 1]
- = 3 Pi / 4
- #> ArcTan[1, -1]
- = -Pi / 4
- #> ArcTan[-1, -1]
- = -3 Pi / 4
-
- #> ArcTan[1, 0]
- = 0
- #> ArcTan[-1, 0]
- = Pi
- #> ArcTan[0, 1]
- = Pi / 2
- #> ArcTan[0, -1]
- = -Pi / 2
"""
mpmath_name = "atan"
@@ -603,9 +588,6 @@ class Cos(MPMathFunction):
>> Cos[3 Pi]
= -1
-
- #> Cos[1.5 Pi]
- = -1.83697×10^-16
"""
mpmath_name = "cos"
@@ -815,9 +797,6 @@ class Sin(MPMathFunction):
>> Plot[Sin[x], {x, -Pi, Pi}]
= -Graphics-
-
- #> N[Sin[1], 40]
- = 0.8414709848078965066525023216302989996226
"""
mpmath_name = "sin"
@@ -855,9 +834,6 @@ class Tan(MPMathFunction):
= 0
>> Tan[Pi / 2]
= ComplexInfinity
-
- #> Tan[0.5 Pi]
- = 1.63312×10^16
"""
mpmath_name = "tan"
diff --git a/mathics/builtin/numeric.py b/mathics/builtin/numeric.py
index 44c8999ea..63bf5d88e 100644
--- a/mathics/builtin/numeric.py
+++ b/mathics/builtin/numeric.py
@@ -257,21 +257,6 @@ class N(Builtin):
= F[3.14159265358979300000000000000]
>> N[F[Pi], 30, Method->"sympy"]
= F[3.14159265358979323846264338328]
- #> p=N[Pi,100]
- = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
- #> ToString[p]
- = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
-
- #> N[1.012345678901234567890123, 20]
- = 1.0123456789012345679
-
- #> N[I, 30]
- = 1.00000000000000000000000000000 I
-
- #> N[1.012345678901234567890123, 50]
- = 1.01234567890123456789012
- #> % // Precision
- = 24.
"""
options = {"Method": "Automatic"}
@@ -454,18 +439,6 @@ class Rationalize(Builtin):
Find the exact rational representation of 'N[Pi]'
>> Rationalize[N[Pi], 0]
= 245850922 / 78256779
-
- #> Rationalize[N[Pi] + 0.8 I, x]
- : Tolerance specification x must be a non-negative number.
- = Rationalize[3.14159 + 0.8 I, x]
-
- #> Rationalize[N[Pi] + 0.8 I, -1]
- : Tolerance specification -1 must be a non-negative number.
- = Rationalize[3.14159 + 0.8 I, -1]
-
- #> Rationalize[x, y]
- : Tolerance specification y must be a non-negative number.
- = Rationalize[x, y]
"""
messages = {
@@ -769,17 +742,11 @@ class Sign(SympyFunction):
= 0
>> Sign[{-5, -10, 15, 20, 0}]
= {-1, -1, 1, 1, 0}
- #> Sign[{1, 2.3, 4/5, {-6.7, 0}, {8/9, -10}}]
- = {1, 1, 1, {-1, 0}, {1, -1}}
+
+ For a complex number, 'Sign' returns the phase of the number:
>> Sign[3 - 4*I]
= 3 / 5 - 4 I / 5
- #> Sign[1 - 4*I] == (1/17 - 4 I/17) Sqrt[17]
- = True
- #> Sign[4, 5, 6]
- : Sign called with 3 arguments; 1 argument is expected.
- = Sign[4, 5, 6]
- #> Sign["20"]
- = Sign[20]
+
"""
summary_text = "complex sign of a number"
diff --git a/mathics/builtin/specialfns/bessel.py b/mathics/builtin/specialfns/bessel.py
index e2e2455da..ebe20fea2 100644
--- a/mathics/builtin/specialfns/bessel.py
+++ b/mathics/builtin/specialfns/bessel.py
@@ -24,7 +24,6 @@
class _Bessel(MPMathFunction):
-
attributes = A_LISTABLE | A_NUMERIC_FUNCTION | A_PROTECTED | A_READ_PROTECTED
nargs = {2}
@@ -109,18 +108,6 @@ class AiryAiZero(Builtin):
>> N[AiryAiZero[1]]
= -2.33811
-
- #> AiryAiZero[1]
- = AiryAiZero[1]
-
- #> AiryAiZero[1.]
- = AiryAiZero[1.]
-
- #> AiryAi[AiryAiZero[1]]
- = 0
-
- #> N[AiryAiZero[2], 100]
- = -4.087949444130970616636988701457391060224764699108529754984160876025121946836047394331169160758270562
"""
# TODO: 'AiryAiZero[$k$, $x0$]' - $k$th zero less than x0
@@ -235,18 +222,6 @@ class AiryBiZero(Builtin):
>> N[AiryBiZero[1]]
= -1.17371
-
- #> AiryBiZero[1]
- = AiryBiZero[1]
-
- #> AiryBiZero[1.]
- = AiryBiZero[1.]
-
- #> AiryBi[AiryBiZero[1]]
- = 0
-
- #> N[AiryBiZero[2], 100]
- = -3.271093302836352715680228240166413806300935969100284801485032396261130864238742879252000673830055014
"""
# TODO: 'AiryBiZero[$k$, $x0$]' - $k$th zero less than x0
@@ -380,9 +355,6 @@ class BesselJ(_Bessel):
>> BesselJ[0, 5.2]
= -0.11029
- #> BesselJ[2.5, 1]
- = 0.0494968
-
>> D[BesselJ[n, z], z]
= -BesselJ[1 + n, z] / 2 + BesselJ[-1 + n, z] / 2
diff --git a/mathics/builtin/specialfns/gamma.py b/mathics/builtin/specialfns/gamma.py
index 33746fd11..7369e0ba6 100644
--- a/mathics/builtin/specialfns/gamma.py
+++ b/mathics/builtin/specialfns/gamma.py
@@ -155,8 +155,6 @@ class Factorial(PostfixOperator, MPMathFunction):
>> !a! //FullForm
= Not[Factorial[a]]
- #> 0!
- = 1
"""
attributes = A_NUMERIC_FUNCTION | A_PROTECTED
@@ -301,22 +299,6 @@ class Gamma(MPMathMultiFunction):
Both 'Gamma' and 'Factorial' functions are continuous:
>> Plot[{Gamma[x], x!}, {x, 0, 4}]
= -Graphics-
-
- ## Issue 203
- #> N[Gamma[24/10], 100]
- = 1.242169344504305404913070252268300492431517240992022966055507541481863694148882652446155342679460339
- #> N[N[Gamma[24/10],100]/N[Gamma[14/10],100],100]
- = 1.400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
- #> % // Precision
- = 100.
-
- #> Gamma[1.*^20]
- : Overflow occurred in computation.
- = Overflow[]
-
- ## Needs mpmath support for lowergamma
- #> Gamma[1., 2.]
- = Gamma[1., 2.]
"""
mpmath_names = {
diff --git a/mathics/builtin/specialfns/orthogonal.py b/mathics/builtin/specialfns/orthogonal.py
index 464b148f9..bd2cb002e 100644
--- a/mathics/builtin/specialfns/orthogonal.py
+++ b/mathics/builtin/specialfns/orthogonal.py
@@ -269,9 +269,6 @@ class SphericalHarmonicY(MPMathFunction):
## Results depend on sympy version
>> SphericalHarmonicY[3, 1, theta, phi]
= ...
-
- #> SphericalHarmonicY[1,1,x,y]
- = -Sqrt[6] E ^ (I y) Sin[x] / (4 Sqrt[Pi])
"""
nargs = {4}
diff --git a/mathics/builtin/tensors.py b/mathics/builtin/tensors.py
index d58c86bff..bad1a83f4 100644
--- a/mathics/builtin/tensors.py
+++ b/mathics/builtin/tensors.py
@@ -19,65 +19,17 @@
"""
-from mathics.core.atoms import Integer, String
+from mathics.core.atoms import Integer
from mathics.core.attributes import A_FLAT, A_ONE_IDENTITY, A_PROTECTED
from mathics.core.builtin import BinaryOperator, Builtin
from mathics.core.evaluation import Evaluation
-from mathics.core.expression import Expression
from mathics.core.list import ListExpression
-from mathics.core.symbols import Atom, Symbol, SymbolFalse, SymbolTrue
-from mathics.eval.parts import get_part
-
-
-def get_default_distance(p):
- if all(q.is_numeric() for q in p):
- return Symbol("SquaredEuclideanDistance")
- elif all(q.get_head_name() == "System`List" for q in p):
- dimensions = [get_dimensions(q) for q in p]
- if len(dimensions) < 1:
- return None
- d0 = dimensions[0]
- if not all(d == d0 for d in dimensions[1:]):
- return None
- if len(dimensions[0]) == 1: # vectors?
-
- def is_boolean(x):
- return x.get_head_name() == "System`Symbol" and x in (
- SymbolTrue,
- SymbolFalse,
- )
-
- if all(all(is_boolean(e) for e in q.elements) for q in p):
- return Symbol("JaccardDissimilarity")
- return Symbol("SquaredEuclideanDistance")
- elif all(isinstance(q, String) for q in p):
- return Symbol("EditDistance")
- else:
- from mathics.builtin.colors.color_directives import expression_to_color
-
- if all(expression_to_color(q) is not None for q in p):
- return Symbol("ColorDistance")
-
- return None
-
-
-def get_dimensions(expr, head=None):
- if isinstance(expr, Atom):
- return []
- else:
- if head is not None and not expr.head.sameQ(head):
- return []
- sub_dim = None
- sub = []
- for element in expr.elements:
- sub = get_dimensions(element, expr.head)
- if sub_dim is None:
- sub_dim = sub
- else:
- if sub_dim != sub:
- sub = []
- break
- return [len(expr.elements)] + sub
+from mathics.eval.tensors import (
+ eval_Inner,
+ eval_LeviCivitaTensor,
+ eval_Outer,
+ get_dimensions,
+)
class ArrayDepth(Builtin):
@@ -215,46 +167,7 @@ class Inner(Builtin):
def eval(self, f, list1, list2, g, evaluation: Evaluation):
"Inner[f_, list1_, list2_, g_]"
- m = get_dimensions(list1)
- n = get_dimensions(list2)
-
- if not m or not n:
- evaluation.message("Inner", "normal")
- return
- if list1.get_head() != list2.get_head():
- evaluation.message("Inner", "heads", list1.get_head(), list2.get_head())
- return
- if m[-1] != n[0]:
- evaluation.message("Inner", "incom", m[-1], len(m), list1, n[0], list2)
- return
-
- head = list1.get_head()
- inner_dim = n[0]
-
- def rec(i_cur, j_cur, i_rest, j_rest):
- evaluation.check_stopped()
- if i_rest:
- elements = []
- for i in range(1, i_rest[0] + 1):
- elements.append(rec(i_cur + [i], j_cur, i_rest[1:], j_rest))
- return Expression(head, *elements)
- elif j_rest:
- elements = []
- for j in range(1, j_rest[0] + 1):
- elements.append(rec(i_cur, j_cur + [j], i_rest, j_rest[1:]))
- return Expression(head, *elements)
- else:
-
- def summand(i):
- part1 = get_part(list1, i_cur + [i])
- part2 = get_part(list2, [i] + j_cur)
- return Expression(f, part1, part2)
-
- part = Expression(g, *[summand(i) for i in range(1, inner_dim + 1)])
- # cur_expr.elements.append(part)
- return part
-
- return rec([], [], m[:-1], n[1:])
+ return eval_Inner(f, list1, list2, g, evaluation)
class Outer(Builtin):
@@ -273,10 +186,21 @@ class Outer(Builtin):
Outer product of two matrices:
>> Outer[Times, {{a, b}, {c, d}}, {{1, 2}, {3, 4}}]
= {{{{a, 2 a}, {3 a, 4 a}}, {{b, 2 b}, {3 b, 4 b}}}, {{{c, 2 c}, {3 c, 4 c}}, {{d, 2 d}, {3 d, 4 d}}}}
+
+ Outer product of two sparse arrays:
+ >> Outer[Times, SparseArray[{{1, 2} -> a, {2, 1} -> b}], SparseArray[{{1, 2} -> c, {2, 1} -> d}]]
+ = SparseArray[Automatic, {2, 2, 2, 2}, 0, {{1, 2, 1, 2} -> a c, {1, 2, 2, 1} -> a d, {2, 1, 1, 2} -> b c, {2, 1, 2, 1} -> b d}]
'Outer' of multiple lists:
>> Outer[f, {a, b}, {x, y, z}, {1, 2}]
= {{{f[a, x, 1], f[a, x, 2]}, {f[a, y, 1], f[a, y, 2]}, {f[a, z, 1], f[a, z, 2]}}, {{f[b, x, 1], f[b, x, 2]}, {f[b, y, 1], f[b, y, 2]}, {f[b, z, 1], f[b, z, 2]}}}
+
+ 'Outer' converts input sparse arrays to lists if f=!=Times, or if the input is a mixture of sparse arrays and lists:
+ >> Outer[f, SparseArray[{{1, 2} -> a, {2, 1} -> b}], SparseArray[{{1, 2} -> c, {2, 1} -> d}]]
+ = {{{{f[0, 0], f[0, c]}, {f[0, d], f[0, 0]}}, {{f[a, 0], f[a, c]}, {f[a, d], f[a, 0]}}}, {{{f[b, 0], f[b, c]}, {f[b, d], f[b, 0]}}, {{f[0, 0], f[0, c]}, {f[0, d], f[0, 0]}}}}
+
+ >> Outer[Times, SparseArray[{{1, 2} -> a, {2, 1} -> b}], {c, d}]
+ = {{{0, 0}, {a c, a d}}, {{b c, b d}, {0, 0}}}
Arrays can be ragged:
>> Outer[Times, {{1, 2}}, {{a, b}, {c, d, e}}]
@@ -299,32 +223,7 @@ class Outer(Builtin):
def eval(self, f, lists, evaluation: Evaluation):
"Outer[f_, lists__]"
- lists = lists.get_sequence()
- head = None
- for list in lists:
- if isinstance(list, Atom):
- evaluation.message("Outer", "normal")
- return
- if head is None:
- head = list.head
- elif not list.head.sameQ(head):
- evaluation.message("Outer", "heads", head, list.head)
- return
-
- def rec(item, rest_lists, current):
- evaluation.check_stopped()
- if isinstance(item, Atom) or not item.head.sameQ(head):
- if rest_lists:
- return rec(rest_lists[0], rest_lists[1:], current + [item])
- else:
- return Expression(f, *(current + [item]))
- else:
- elements = []
- for element in item.elements:
- elements.append(rec(element, rest_lists, current))
- return Expression(head, *elements)
-
- return rec(lists[0], lists[1:], [])
+ return eval_Outer(f, lists, evaluation)
class RotationTransform(Builtin):
@@ -450,7 +349,7 @@ class Transpose(Builtin):
:WMA: https://reference.wolfram.com/language/ref/Transpose.html)
- - 'Tranpose[$m$]'
+
- 'Transpose[$m$]'
- transposes rows and columns in the matrix $m$.
@@ -490,3 +389,57 @@ def eval(self, m, evaluation: Evaluation):
else:
result[col_index].append(item)
return ListExpression(*[ListExpression(*row) for row in result])
+
+
+class ConjugateTranspose(Builtin):
+ """
+
+ :Conjugate transpose: https://en.wikipedia.org/wiki/Conjugate_transpose (
+ :WMA: https://reference.wolfram.com/language/ref/ConjugateTranspose.html)
+
+
+ - 'ConjugateTranspose[$m$]'
+
- gives the conjugate transpose of $m$.
+
+
+ >> ConjugateTranspose[{{0, I}, {0, 0}}]
+ = {{0, 0}, {-I, 0}}
+
+ >> ConjugateTranspose[{{1, 2 I, 3}, {3 + 4 I, 5, I}}]
+ = {{1, 3 - 4 I}, {-2 I, 5}, {3, -I}}
+ """
+
+ rules = {
+ "ConjugateTranspose[m_]": "Conjugate[Transpose[m]]",
+ }
+ summary_text = "give the conjugate transpose"
+
+
+class LeviCivitaTensor(Builtin):
+ """
+ :Levi-Civita tensor:https://en.wikipedia.org/wiki/Levi-Civita_symbol \
+ (:WMA link:https://reference.wolfram.com/language/ref/LeviCivitaTensor.html)
+
+
+ - 'LeviCivitaTensor[$d$]'
+
- gives the $d$-dimensional Levi-Civita totally antisymmetric tensor.
+
+
+ >> LeviCivitaTensor[3]
+ = SparseArray[Automatic, {3, 3, 3}, 0, {{1, 2, 3} -> 1, {1, 3, 2} -> -1, {2, 1, 3} -> -1, {2, 3, 1} -> 1, {3, 1, 2} -> 1, {3, 2, 1} -> -1}]
+
+ >> LeviCivitaTensor[3, List]
+ = {{{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, {{0, 0, -1}, {0, 0, 0}, {1, 0, 0}}, {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0}}}
+ """
+
+ rules = {
+ "LeviCivitaTensor[d_Integer]/; Greater[d, 0]": "LeviCivitaTensor[d, SparseArray]",
+ "LeviCivitaTensor[d_Integer, List] /; Greater[d, 0]": "LeviCivitaTensor[d, SparseArray] // Normal",
+ }
+
+ summary_text = "give the Levi-Civita tensor with a given dimension"
+
+ def eval(self, d, type, evaluation: Evaluation):
+ "LeviCivitaTensor[d_Integer, type_]"
+
+ return eval_LeviCivitaTensor(d, type)
diff --git a/mathics/builtin/testing_expressions/list_oriented.py b/mathics/builtin/testing_expressions/list_oriented.py
index b99fe2040..b2f819331 100644
--- a/mathics/builtin/testing_expressions/list_oriented.py
+++ b/mathics/builtin/testing_expressions/list_oriented.py
@@ -7,10 +7,10 @@
from mathics.core.evaluation import Evaluation
from mathics.core.exceptions import InvalidLevelspecError
from mathics.core.expression import Expression
-from mathics.core.rules import Pattern
from mathics.core.symbols import Atom, SymbolFalse, SymbolTrue
-from mathics.core.systemsymbols import SymbolSubsetQ
+from mathics.core.systemsymbols import SymbolSubsetQ # , SymbolSparseArray
from mathics.eval.parts import python_levelspec
+from mathics.eval.testing_expressions import check_ArrayQ # , check_SparseArrayQ
class ArrayQ(Builtin):
@@ -51,37 +51,10 @@ class ArrayQ(Builtin):
def eval(self, expr, pattern, test, evaluation: Evaluation):
"ArrayQ[expr_, pattern_, test_]"
- pattern = Pattern.create(pattern)
-
- dims = [len(expr.get_elements())] # to ensure an atom is not an array
-
- def check(level, expr):
- if not expr.has_form("List", None):
- test_expr = Expression(test, expr)
- if test_expr.evaluate(evaluation) != SymbolTrue:
- return False
- level_dim = None
- else:
- level_dim = len(expr.elements)
-
- if len(dims) > level:
- if dims[level] != level_dim:
- return False
- else:
- dims.append(level_dim)
- if level_dim is not None:
- for element in expr.elements:
- if not check(level + 1, element):
- return False
- return True
-
- if not check(0, expr):
- return SymbolFalse
+ # if not isinstance(expr, Atom) and expr.head.sameQ(SymbolSparseArray):
+ # return check_SparseArrayQ(expr, pattern, test, evaluation)
- depth = len(dims) - 1 # None doesn't count
- if not pattern.does_match(Integer(depth), evaluation):
- return SymbolFalse
- return SymbolTrue
+ return check_ArrayQ(expr, pattern, test, evaluation)
class DisjointQ(Test):
diff --git a/mathics/core/symbols.py b/mathics/core/symbols.py
index adfe063e9..fca9cbd27 100644
--- a/mathics/core/symbols.py
+++ b/mathics/core/symbols.py
@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
import time
-from typing import Any, FrozenSet, List, Optional, Tuple
+from typing import Any, FrozenSet, List, Optional
from mathics.core.element import (
BaseElement,
@@ -17,6 +17,7 @@
sympy_symbol_prefix = "_Mathics_User_"
sympy_slot_prefix = "_Mathics_Slot_"
+
# FIXME: This is repeated below
class NumericOperators:
"""
@@ -199,7 +200,8 @@ class Atom(BaseElement):
Atom is not a directly-mentioned WL entity, although conceptually
it very much seems to exist.
- The other kinds expression element is a Builtin, e.g. `ByteArray``, `CompiledCode`` or ``Image``.
+ The other kinds expression element is a Builtin, e.g. `ByteArray``, `CompiledCode``
+ or ``Image``.
"""
_head_name = ""
@@ -251,8 +253,8 @@ def get_atom_name(self) -> str:
def get_atoms(self, include_heads=True) -> List["Atom"]:
return [self]
- # We seem to need this because the caller doesn't distinguish something with elements
- # from a single atom.
+ # We seem to need this because the caller doesn't distinguish
+ # something with elements from a single atom.
def get_elements(self):
return []
@@ -262,14 +264,18 @@ def get_head(self) -> "Symbol":
def get_head_name(self) -> "str":
return self.class_head_name # System`" + self.__class__.__name__
- # def get_option_values(self, evaluation, allow_symbols=False, stop_on_error=True):
+ # def get_option_values(self, evaluation, allow_symbols=False,
+ # stop_on_error=True):
# """
# Build a dictionary of options from an expression.
- # For example Symbol("Integrate").get_option_values(evaluation, allow_symbols=True)
- # will return a list of options associated to the definition of the symbol "Integrate".
+ # For example Symbol("Integrate").get_option_values(evaluation,
+ # allow_symbols=True)
+ # will return a list of options associated to the definition of the symbol
+ # "Integrate".
# If self is not an expression,
# """
- # print("get_option_values is trivial for ", (self, stop_on_error, allow_symbols ))
+ # print("get_option_values is trivial for ", (self, stop_on_error,
+ # allow_symbols ))
# 1/0
# return None if stop_on_error else {}
@@ -661,7 +667,6 @@ class SymbolConstant(Symbol):
# We use __new__ here to unsure that two Integer's that have the same value
# return the same object.
def __new__(cls, name, value):
-
name = ensure_context(name)
self = cls._symbol_constants.get(name)
if self is None:
diff --git a/mathics/eval/tensors.py b/mathics/eval/tensors.py
new file mode 100644
index 000000000..596c792b0
--- /dev/null
+++ b/mathics/eval/tensors.py
@@ -0,0 +1,244 @@
+import itertools
+
+from sympy.combinatorics import Permutation
+from sympy.utilities.iterables import permutations
+
+from mathics.core.atoms import Integer, Integer0, Integer1, String
+from mathics.core.convert.python import from_python
+from mathics.core.evaluation import Evaluation
+from mathics.core.expression import Expression
+from mathics.core.list import ListExpression
+from mathics.core.symbols import (
+ Atom,
+ Symbol,
+ SymbolFalse,
+ SymbolList,
+ SymbolTimes,
+ SymbolTrue,
+)
+from mathics.core.systemsymbols import (
+ SymbolAutomatic,
+ SymbolNormal,
+ SymbolRule,
+ SymbolSparseArray,
+)
+from mathics.eval.parts import get_part
+
+
+def get_default_distance(p):
+ if all(q.is_numeric() for q in p):
+ return Symbol("SquaredEuclideanDistance")
+ elif all(q.get_head_name() == "System`List" for q in p):
+ dimensions = [get_dimensions(q) for q in p]
+ if len(dimensions) < 1:
+ return None
+ d0 = dimensions[0]
+ if not all(d == d0 for d in dimensions[1:]):
+ return None
+ if len(dimensions[0]) == 1: # vectors?
+
+ def is_boolean(x):
+ return x.get_head_name() == "System`Symbol" and x in (
+ SymbolTrue,
+ SymbolFalse,
+ )
+
+ if all(all(is_boolean(e) for e in q.elements) for q in p):
+ return Symbol("JaccardDissimilarity")
+ return Symbol("SquaredEuclideanDistance")
+ elif all(isinstance(q, String) for q in p):
+ return Symbol("EditDistance")
+ else:
+ from mathics.builtin.colors.color_directives import expression_to_color
+
+ if all(expression_to_color(q) is not None for q in p):
+ return Symbol("ColorDistance")
+
+ return None
+
+
+def get_dimensions(expr, head=None):
+ if isinstance(expr, Atom):
+ return []
+ else:
+ if head is not None and not expr.head.sameQ(head):
+ return []
+ sub_dim = None
+ sub = []
+ for element in expr.elements:
+ sub = get_dimensions(element, expr.head)
+ if sub_dim is None:
+ sub_dim = sub
+ else:
+ if sub_dim != sub:
+ sub = []
+ break
+ return [len(expr.elements)] + sub
+
+
+def eval_Inner(f, list1, list2, g, evaluation: Evaluation):
+ "Evaluates recursively the inner product of list1 and list2"
+
+ m = get_dimensions(list1)
+ n = get_dimensions(list2)
+
+ if not m or not n:
+ evaluation.message("Inner", "normal")
+ return
+ if list1.get_head() != list2.get_head():
+ evaluation.message("Inner", "heads", list1.get_head(), list2.get_head())
+ return
+ if m[-1] != n[0]:
+ evaluation.message("Inner", "incom", m[-1], len(m), list1, n[0], list2)
+ return
+
+ head = list1.get_head()
+ inner_dim = n[0]
+
+ def rec(i_cur, j_cur, i_rest, j_rest):
+ evaluation.check_stopped()
+ if i_rest:
+ elements = []
+ for i in range(1, i_rest[0] + 1):
+ elements.append(rec(i_cur + [i], j_cur, i_rest[1:], j_rest))
+ return Expression(head, *elements)
+ elif j_rest:
+ elements = []
+ for j in range(1, j_rest[0] + 1):
+ elements.append(rec(i_cur, j_cur + [j], i_rest, j_rest[1:]))
+ return Expression(head, *elements)
+ else:
+
+ def summand(i):
+ part1 = get_part(list1, i_cur + [i])
+ part2 = get_part(list2, [i] + j_cur)
+ return Expression(f, part1, part2)
+
+ part = Expression(g, *[summand(i) for i in range(1, inner_dim + 1)])
+ # cur_expr.elements.append(part)
+ return part
+
+ return rec([], [], m[:-1], n[1:])
+
+
+def eval_Outer(f, lists, evaluation: Evaluation):
+ "Evaluates recursively the outer product of lists"
+
+ # If f=!=Times, or lists contain both SparseArray and List, then convert all SparseArrays to Lists
+ lists = lists.get_sequence()
+ head = None
+ sparse_to_list = f != SymbolTimes
+ contain_sparse = False
+ contain_list = False
+ for _list in lists:
+ if _list.head.sameQ(SymbolSparseArray):
+ contain_sparse = True
+ if _list.head.sameQ(SymbolList):
+ contain_list = True
+ sparse_to_list = sparse_to_list or (contain_sparse and contain_list)
+ if sparse_to_list:
+ break
+ if sparse_to_list:
+ new_lists = []
+ for _list in lists:
+ if isinstance(_list, Atom):
+ evaluation.message("Outer", "normal")
+ return
+ if sparse_to_list:
+ if _list.head.sameQ(SymbolSparseArray):
+ _list = Expression(SymbolNormal, _list).evaluate(evaluation)
+ new_lists.append(_list)
+ if head is None:
+ head = _list.head
+ elif not _list.head.sameQ(head):
+ evaluation.message("Outer", "heads", head, _list.head)
+ return
+ if sparse_to_list:
+ lists = new_lists
+
+ def rec(item, rest_lists, current):
+ evaluation.check_stopped()
+ if isinstance(item, Atom) or not item.head.sameQ(head):
+ if rest_lists:
+ return rec(rest_lists[0], rest_lists[1:], current + [item])
+ else:
+ return Expression(f, *(current + [item]))
+ else:
+ elements = []
+ for element in item.elements:
+ elements.append(rec(element, rest_lists, current))
+ return Expression(head, *elements)
+
+ def rec_sparse(item, rest_lists, current):
+ evaluation.check_stopped()
+ if isinstance(item, tuple): # (rules)
+ elements = []
+ for element in item:
+ elements.extend(rec_sparse(element, rest_lists, current))
+ return tuple(elements)
+ else: # rule
+ _pos, _val = item.elements
+ if rest_lists:
+ return rec_sparse(
+ rest_lists[0],
+ rest_lists[1:],
+ (current[0] + _pos.elements, current[1] * _val),
+ )
+ else:
+ return (
+ Expression(
+ SymbolRule,
+ ListExpression(*(current[0] + _pos.elements)),
+ current[1] * _val,
+ ),
+ )
+
+ # head != SparseArray
+ if not head.sameQ(SymbolSparseArray):
+ return rec(lists[0], lists[1:], [])
+
+ # head == SparseArray
+ dims = []
+ val = Integer1
+ data = [] # data = [(rules), ...]
+ for _list in lists:
+ _dims, _val, _rules = _list.elements[1:]
+ dims.extend(_dims)
+ val *= _val
+ if _val == Integer0: # _val==0, append (_rules)
+ data.append(_rules.elements)
+ else: # _val!=0, append (_rules, other pos->_val)
+ other_pos = []
+ for pos in itertools.product(*(range(1, d.value + 1) for d in _dims)):
+ other_pos.append(ListExpression(*(Integer(i) for i in pos)))
+ rules_pos = set(rule.elements[0] for rule in _rules.elements)
+ other_pos = set(other_pos) - rules_pos
+ other_rules = []
+ for pos in other_pos:
+ other_rules.append(Expression(SymbolRule, pos, _val))
+ data.append(_rules.elements + tuple(other_rules))
+ dims = ListExpression(*dims)
+ return Expression(
+ SymbolSparseArray,
+ SymbolAutomatic,
+ dims,
+ val,
+ ListExpression(*rec_sparse(data[0], data[1:], ((), Integer1))),
+ )
+
+
+def eval_LeviCivitaTensor(d, type):
+ "Evaluates Levi-Civita tensor of rank d"
+
+ if isinstance(d, Integer) and type == SymbolSparseArray:
+ d = d.get_int_value()
+ perms = list(permutations(list(range(1, d + 1))))
+ rules = [
+ Expression(
+ SymbolRule,
+ from_python(p),
+ from_python(Permutation.from_sequence(p).signature()),
+ )
+ for p in perms
+ ]
+ return Expression(SymbolSparseArray, from_python(rules), from_python([d] * d))
diff --git a/mathics/eval/testing_expressions.py b/mathics/eval/testing_expressions.py
index 4046d0c8c..2bd751944 100644
--- a/mathics/eval/testing_expressions.py
+++ b/mathics/eval/testing_expressions.py
@@ -2,13 +2,15 @@
import sympy
-from mathics.core.atoms import Complex, Integer0, Integer1, IntegerM1
+from mathics.core.atoms import Complex, Integer, Integer0, Integer1, IntegerM1
+from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
-from mathics.core.systemsymbols import SymbolDirectedInfinity
+from mathics.core.rules import Pattern
+from mathics.core.symbols import SymbolFalse, SymbolTimes, SymbolTrue
+from mathics.core.systemsymbols import SymbolDirectedInfinity, SymbolSparseArray
def do_cmp(x1, x2) -> Optional[int]:
-
# don't attempt to compare complex numbers
for x in (x1, x2):
# TODO: Send message General::nord
@@ -99,3 +101,64 @@ def expr_min(elements):
def is_number(sympy_value) -> bool:
return hasattr(sympy_value, "is_number") or isinstance(sympy_value, sympy.Float)
+
+
+def check_ArrayQ(expr, pattern, test, evaluation: Evaluation):
+ "Check if expr is an Array which test yields true for each of its elements."
+
+ pattern = Pattern.create(pattern)
+
+ dims = [len(expr.get_elements())] # to ensure an atom is not an array
+
+ def check(level, expr):
+ if not expr.has_form("List", None):
+ test_expr = Expression(test, expr)
+ if test_expr.evaluate(evaluation) != SymbolTrue:
+ return False
+ level_dim = None
+ else:
+ level_dim = len(expr.elements)
+
+ if len(dims) > level:
+ if dims[level] != level_dim:
+ return False
+ else:
+ dims.append(level_dim)
+ if level_dim is not None:
+ for element in expr.elements:
+ if not check(level + 1, element):
+ return False
+ return True
+
+ if not check(0, expr):
+ return SymbolFalse
+
+ depth = len(dims) - 1 # None doesn't count
+ if not pattern.does_match(Integer(depth), evaluation):
+ return SymbolFalse
+
+ return SymbolTrue
+
+
+def check_SparseArrayQ(expr, pattern, test, evaluation: Evaluation):
+ "Check if expr is a SparseArray which test yields true for each of its elements."
+
+ if not expr.head.sameQ(SymbolSparseArray):
+ return SymbolFalse
+
+ pattern = Pattern.create(pattern)
+ dims, default_value, rules = expr.elements[1:]
+ if not pattern.does_match(Integer(len(dims.elements)), evaluation):
+ return SymbolFalse
+
+ array_size = Expression(SymbolTimes, *dims.elements).evaluate(evaluation)
+ if array_size.value > len(rules.elements): # expr is not full
+ test_expr = Expression(test, default_value) # test default value
+ if test_expr.evaluate(evaluation) != SymbolTrue:
+ return SymbolFalse
+ for rule in rules.elements:
+ test_expr = Expression(test, rule.elements[-1])
+ if test_expr.evaluate(evaluation) != SymbolTrue:
+ return SymbolFalse
+
+ return SymbolTrue
diff --git a/setup.py b/setup.py
index db43c728f..d78268723 100644
--- a/setup.py
+++ b/setup.py
@@ -240,18 +240,18 @@ def subdirs(root, file="*.*", depth=10):
description="A general-purpose computer algebra system.",
license="GPL",
url="https://mathics.org/",
- download_url="https://github.com/Mathics/mathics-core/releases",
+ download_url="https://github.com/Mathics3/mathics-core/releases",
keywords=["Mathematica", "Wolfram", "Interpreter", "Shell", "Math", "CAS"],
classifiers=[
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Programming Language :: Python",
- "Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Scientific/Engineering",
diff --git a/test/builtin/arithmetic/test_basic.py b/test/builtin/arithmetic/test_basic.py
index 1bec99de7..07e83f1be 100644
--- a/test/builtin/arithmetic/test_basic.py
+++ b/test/builtin/arithmetic/test_basic.py
@@ -449,3 +449,35 @@ def test_cuberoot(str_expr, str_expected, msgs, failmsg):
check_evaluation(
str_expr, str_expected, expected_messages=msgs, failure_message=failmsg
)
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ ## Issue #302
+ ## The sum should not converge since the first term is 1/0.
+ (
+ "Sum[i / Log[i], {i, 1, Infinity}]",
+ None,
+ "Sum[i / Log[i], {i, 1, Infinity}]",
+ None,
+ ),
+ (
+ "Sum[Cos[Pi i], {i, 1, Infinity}]",
+ None,
+ "Sum[Cos[i Pi], {i, 1, Infinity}]",
+ None,
+ ),
+ ],
+)
+def test_private_doctests_arithmetic(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/files_io/test_files.py b/test/builtin/files_io/test_files.py
index 3e0a2bf6c..adb0dcc52 100644
--- a/test/builtin/files_io/test_files.py
+++ b/test/builtin/files_io/test_files.py
@@ -80,6 +80,262 @@ def test_close():
), f"temporary filename {temp_filename} should not appear"
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ ('Close["abc"]', ("abc is not open.",), "Close[abc]", None),
+ (
+ "exp = Sin[1]; FilePrint[exp]",
+ ("File specification Sin[1] is not a string of one or more characters.",),
+ "FilePrint[Sin[1]]",
+ None,
+ ),
+ (
+ 'FilePrint["somenonexistentpath_h47sdmk^&h4"]',
+ ("Cannot open somenonexistentpath_h47sdmk^&h4.",),
+ "FilePrint[somenonexistentpath_h47sdmk^&h4]",
+ None,
+ ),
+ (
+ 'FilePrint[""]',
+ ("File specification is not a string of one or more characters.",),
+ "FilePrint[]",
+ None,
+ ),
+ (
+ 'Get["SomeTypoPackage`"]',
+ ("Cannot open SomeTypoPackage`.",),
+ "$Failed",
+ None,
+ ),
+ ## Parser Tests
+ (
+ "Hold[<< ~/some_example/dir/] // FullForm",
+ None,
+ 'Hold[Get["~/some_example/dir/"]]',
+ None,
+ ),
+ (
+ r"Hold[<<`/.\-_:$*~?] // FullForm",
+ None,
+ r'Hold[Get["`/.\\\\-_:$*~?"]]',
+ None,
+ ),
+ (
+ "OpenRead[]",
+ ("OpenRead called with 0 arguments; 1 argument is expected.",),
+ "OpenRead[]",
+ None,
+ ),
+ (
+ "OpenRead[y]",
+ ("File specification y is not a string of one or more characters.",),
+ "OpenRead[y]",
+ None,
+ ),
+ (
+ 'OpenRead[""]',
+ ("File specification is not a string of one or more characters.",),
+ "OpenRead[]",
+ None,
+ ),
+ (
+ 'OpenRead["MathicsNonExampleFile"]',
+ ("Cannot open MathicsNonExampleFile.",),
+ "OpenRead[MathicsNonExampleFile]",
+ None,
+ ),
+ (
+ 'fd=OpenRead["ExampleData/EinsteinSzilLetter.txt", BinaryFormat -> True, CharacterEncoding->"UTF8"]//Head',
+ None,
+ "InputStream",
+ None,
+ ),
+ (
+ "Close[fd]; fd=.;fd=OpenWrite[BinaryFormat -> True]//Head",
+ None,
+ "OutputStream",
+ None,
+ ),
+ (
+ 'DeleteFile[Close[fd]];fd=.;appendFile = OpenAppend["MathicsNonExampleFile"]//{#1[[0]],#1[[1]]}&',
+ None,
+ "{OutputStream, MathicsNonExampleFile}",
+ None,
+ ),
+ (
+ "Close[appendFile]",
+ None,
+ "Close[{OutputStream, MathicsNonExampleFile}]",
+ None,
+ ),
+ ('DeleteFile["MathicsNonExampleFile"]', None, "Null", None),
+ ## writing to dir
+ ("x >>> /var/", ("Cannot open /var/.",), "x >>> /var/", None),
+ ## writing to read only file
+ (
+ "x >>> /proc/uptime",
+ ("Cannot open /proc/uptime.",),
+ "x >>> /proc/uptime",
+ None,
+ ),
+ ## Malformed InputString
+ (
+ "Read[InputStream[String], {Word, Number}]",
+ None,
+ "Read[InputStream[String], {Word, Number}]",
+ None,
+ ),
+ ## Correctly formed InputString but not open
+ (
+ "Read[InputStream[String, -1], {Word, Number}]",
+ ("InputStream[String, -1] is not open.",),
+ "Read[InputStream[String, -1], {Word, Number}]",
+ None,
+ ),
+ ('stream = StringToStream[""];Read[stream, Word]', None, "EndOfFile", None),
+ ("Read[stream, Word]", None, "EndOfFile", None),
+ ("Close[stream];", None, "Null", None),
+ (
+ 'stream = StringToStream["123xyz 321"]; Read[stream, Number]',
+ None,
+ "123",
+ None,
+ ),
+ ("Quiet[Read[stream, Number]]", None, "$Failed", None),
+ ## Real
+ ('stream = StringToStream["123, 4abc"];Read[stream, Real]', None, "123.", None),
+ ("Read[stream, Real]", None, "4.", None),
+ ("Quiet[Read[stream, Number]]", None, "$Failed", None),
+ ("Close[stream];", None, "Null", None),
+ (
+ 'stream = StringToStream["1.523E-19"]; Read[stream, Real]',
+ None,
+ "1.523×10^-19",
+ None,
+ ),
+ ("Close[stream];", None, "Null", None),
+ (
+ 'stream = StringToStream["-1.523e19"]; Read[stream, Real]',
+ None,
+ "-1.523×10^19",
+ None,
+ ),
+ ("Close[stream];", None, "Null", None),
+ (
+ 'stream = StringToStream["3*^10"]; Read[stream, Real]',
+ None,
+ "3.×10^10",
+ None,
+ ),
+ ("Close[stream];", None, "Null", None),
+ (
+ 'stream = StringToStream["3.*^10"]; Read[stream, Real]',
+ None,
+ "3.×10^10",
+ None,
+ ),
+ ("Close[stream];", None, "Null", None),
+ ## Expression
+ (
+ 'stream = StringToStream["x + y Sin[z]"]; Read[stream, Expression]',
+ None,
+ "x + y Sin[z]",
+ None,
+ ),
+ ("Close[stream];", None, "Null", None),
+ ## ('stream = Quiet[StringToStream["Sin[1 123"]; Read[stream, Expression]]', None,'$Failed', None),
+ (
+ 'stream = StringToStream["123 abc"]; Quiet[Read[stream, {Word, Number}]]',
+ None,
+ "$Failed",
+ None,
+ ),
+ ("Close[stream];", None, "Null", None),
+ (
+ 'stream = StringToStream["123 123"]; Read[stream, {Real, Number}]',
+ None,
+ "{123., 123}",
+ None,
+ ),
+ ("Close[stream];", None, "Null", None),
+ (
+ "Quiet[Read[stream, {Real}]]//{#1[[0]],#1[[1]][[0]],#1[[1]][[1]],#1[[2]]}&",
+ None,
+ "{Read, InputStream, String, {Real}}",
+ None,
+ ),
+ (
+ r'stream = StringToStream["\"abc123\""];ReadList[stream, "Invalid"]//{#1[[0]],#1[[2]]}&',
+ ("Invalid is not a valid format specification.",),
+ "{ReadList, Invalid}",
+ None,
+ ),
+ ("Close[stream];", None, "Null", None),
+ (
+ 'ReadList[StringToStream["a 1 b 2"], {Word, Number}, 1]',
+ None,
+ "{{a, 1}}",
+ None,
+ ),
+ ('stream = StringToStream["Mathics is cool!"];', None, "Null", None),
+ ("SetStreamPosition[stream, -5]", ("Invalid I/O Seek.",), "0", None),
+ (
+ '(strm = StringToStream["abc 123"])//{#1[[0]],#1[[1]]}&',
+ None,
+ "{InputStream, String}",
+ None,
+ ),
+ ("Read[strm, Word]", None, "abc", None),
+ ("Read[strm, Number]", None, "123", None),
+ ("Close[strm]", None, "String", None),
+ ("(low=OpenWrite[])//Head", None, "OutputStream", None),
+ (
+ "Streams[low[[1]]]//{#1[[0]],#1[[1]][[0]]}&",
+ None,
+ "{List, OutputStream}",
+ None,
+ ),
+ ('Streams["some_nonexistent_name"]', None, "{}", None),
+ (
+ "stream = OpenWrite[]; WriteString[stream, 100, 1 + x + y, Sin[x + y]]",
+ None,
+ "Null",
+ None,
+ ),
+ ("(pathname = Close[stream])//Head", None, "String", None),
+ ("FilePrint[pathname]", ("1001 + x + ySin[x + y]",), "Null", None),
+ ("DeleteFile[pathname];", None, "Null", None),
+ (
+ "stream = OpenWrite[];WriteString[stream];(pathname = Close[stream])//Head",
+ None,
+ "String",
+ None,
+ ),
+ ("FilePrint[pathname]", None, "Null", None),
+ (
+ "WriteString[pathname, abc];(laststrm=Streams[pathname][[1]])//Head",
+ None,
+ "OutputStream",
+ None,
+ ),
+ ("Close[laststrm];FilePrint[pathname]", ("abc",), "Null", None),
+ ("DeleteFile[pathname];Clear[pathname];", None, "Null", None),
+ ],
+)
+def test_private_doctests_files(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
+
+
# I do not know what this is it supposed to test with this...
# def test_Inputget_and_put():
# stream = Expression('Plus', Symbol('x'), Integer(2))
diff --git a/test/builtin/files_io/test_filesystem.py b/test/builtin/files_io/test_filesystem.py
new file mode 100644
index 000000000..32e2c5b82
--- /dev/null
+++ b/test/builtin/files_io/test_filesystem.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+"""
+Unit tests from builtins/files_io/filesystem.py
+"""
+import os.path as osp
+import sys
+from test.helper import check_evaluation, evaluate
+
+import pytest
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ (
+ 'AbsoluteFileName["Some/NonExistant/Path.ext"]',
+ ("File not found during AbsoluteFileName[Some/NonExistant/Path.ext].",),
+ "$Failed",
+ None,
+ ),
+ ('DirectoryName["a/b/c", 3] // InputForm', None, '""', None),
+ ('DirectoryName[""] // InputForm', None, '""', None),
+ (
+ 'DirectoryName["a/b/c", x]',
+ (
+ "Positive machine-sized integer expected at position 2 in DirectoryName[a/b/c, x].",
+ ),
+ "DirectoryName[a/b/c, x]",
+ None,
+ ),
+ (
+ 'DirectoryName["a/b/c", -1]',
+ (
+ "Positive machine-sized integer expected at position 2 in DirectoryName[a/b/c, -1].",
+ ),
+ "DirectoryName[a/b/c, -1]",
+ None,
+ ),
+ (
+ "DirectoryName[x]",
+ ("String expected at position 1 in DirectoryName[x].",),
+ "DirectoryName[x]",
+ None,
+ ),
+ ('FileBaseName["file."]', None, "file", None),
+ ('FileBaseName["file"]', None, "file", None),
+ ('FileExtension["file."]', None, "", None),
+ ('FileExtension["file"]', None, "", None),
+ ('FileInformation["ExampleData/missing_file.jpg"]', None, "{}", None),
+ ('FindFile["SomeTypoPackage`"]', None, "$Failed", None),
+ (
+ 'SetDirectory["MathicsNonExample"]',
+ ("Cannot set current directory to MathicsNonExample.",),
+ "$Failed",
+ None,
+ ),
+ (
+ 'Needs["SomeFakePackageOrTypo`"]',
+ (
+ "Cannot open SomeFakePackageOrTypo`.",
+ "Context SomeFakePackageOrTypo` was not created when Needs was evaluated.",
+ ),
+ "$Failed",
+ None,
+ ),
+ (
+ 'Needs["VectorAnalysis"]',
+ (
+ "Invalid context specified at position 1 in Needs[VectorAnalysis]. A context must consist of valid symbol names separated by and ending with `.",
+ ),
+ "Needs[VectorAnalysis]",
+ None,
+ ),
+ ],
+)
+def test_private_doctests_filesystem(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/files_io/test_importexport.py b/test/builtin/files_io/test_importexport.py
index c85d8f59c..f51c38dfe 100644
--- a/test/builtin/files_io/test_importexport.py
+++ b/test/builtin/files_io/test_importexport.py
@@ -3,13 +3,12 @@
import os.path as osp
import sys
import tempfile
+from test.helper import check_evaluation, evaluate, session
import pytest
from mathics.builtin.atomic.strings import to_python_encoding
-from ...helper import session
-
# def test_import():
# eaccent = "\xe9"
# for str_expr, str_expected, message in (
@@ -82,6 +81,185 @@ def test_export():
assert data.endswith("")
+"""
+
+ ## Compression
+ ## #> Export["abc.txt", 1+x, "ZIP"] (* MMA Bug - Export::type *)
+ ## : {ZIP} is not a valid set of export elements for the Text format.
+ ## = $Failed
+ ## #> Export["abc.txt", 1+x, "BZIP"] (* MMA Bug - General::stop *)
+ ## : {BZIP} is not a valid set of export elements for the Text format.
+ ## = $Failed
+ ## #> Export["abc.txt", 1+x, {"BZIP", "ZIP", "Text"}]
+ ## = abc.txt
+ ## #> Export["abc.txt", 1+x, {"GZIP", "Text"}]
+ ## = abc.txt
+ ## #> Export["abc.txt", 1+x, {"BZIP2", "Text"}]
+ ## = abc.txt
+
+ ## Doesn't work on Microsoft Windows
+ ## S> FileFormat["ExampleData/benzene.xyz"]
+ ## = XYZ
+
+"""
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ (r'Quiet[URLFetch["https://", {}]]', None, "$Failed", None),
+ # (r'Quiet[URLFetch["https://www.example.com", {}]]', None,
+ # "...", None),
+ (
+ 'Import["ExampleData/ExampleData.tx"]',
+ ("File not found during Import.",),
+ "$Failed",
+ None,
+ ),
+ (
+ "Import[x]",
+ ("First argument x is not a valid file, directory, or URL specification.",),
+ "$Failed",
+ None,
+ ),
+ ## CSV
+ (
+ 'Import["ExampleData/numberdata.csv", "Elements"]',
+ None,
+ "{Data, Grid}",
+ None,
+ ),
+ (
+ 'Import["ExampleData/numberdata.csv", "Data"]',
+ None,
+ "{{0.88, 0.60, 0.94}, {0.76, 0.19, 0.51}, {0.97, 0.04, 0.26}, {0.33, 0.74, 0.79}, {0.42, 0.64, 0.56}}",
+ None,
+ ),
+ (
+ 'Import["ExampleData/numberdata.csv"]',
+ None,
+ "{{0.88, 0.60, 0.94}, {0.76, 0.19, 0.51}, {0.97, 0.04, 0.26}, {0.33, 0.74, 0.79}, {0.42, 0.64, 0.56}}",
+ None,
+ ),
+ (
+ 'Import["ExampleData/numberdata.csv", "FieldSeparators" -> "."]',
+ None,
+ "{{0, 88,0, 60,0, 94}, {0, 76,0, 19,0, 51}, {0, 97,0, 04,0, 26}, {0, 33,0, 74,0, 79}, {0, 42,0, 64,0, 56}}",
+ None,
+ ),
+ (
+ 'Import["ExampleData/Middlemarch.txt"];',
+ ("An invalid unicode sequence was encountered and ignored.",),
+ "Null",
+ None,
+ ),
+ ## XML
+ (
+ 'MatchQ[Import["ExampleData/InventionNo1.xml", "Tags"],{__String}]',
+ None,
+ "True",
+ None,
+ ),
+ ("ImportString[x]", ("First argument x is not a string.",), "$Failed", None),
+ ## CSV
+ (
+ 'datastring = "0.88, 0.60, 0.94\\n.076, 0.19, .51\\n0.97, 0.04, .26";ImportString[datastring, "Elements"]',
+ None,
+ "{Data, Lines, Plaintext, String, Words}",
+ None,
+ ),
+ ('ImportString[datastring, {"CSV","Elements"}]', None, "{Data, Grid}", None),
+ (
+ 'ImportString[datastring, {"CSV", "Data"}]',
+ None,
+ "{{0.88, 0.60, 0.94}, {.076, 0.19, .51}, {0.97, 0.04, .26}}",
+ None,
+ ),
+ (
+ "ImportString[datastring]",
+ None,
+ "0.88, 0.60, 0.94\n.076, 0.19, .51\n0.97, 0.04, .26",
+ None,
+ ),
+ (
+ 'ImportString[datastring, "CSV","FieldSeparators" -> "."]',
+ None,
+ "{{0, 88, 0, 60, 0, 94}, {076, 0, 19, , 51}, {0, 97, 0, 04, , 26}}",
+ None,
+ ),
+ ## Invalid Filename
+ (
+ 'Export["abc.", 1+2]',
+ ("Cannot infer format of file abc..",),
+ "$Failed",
+ None,
+ ),
+ (
+ 'Export[".ext", 1+2]',
+ ("Cannot infer format of file .ext.",),
+ "$Failed",
+ None,
+ ),
+ (
+ "Export[x, 1+2]",
+ ("First argument x is not a valid file specification.",),
+ "$Failed",
+ None,
+ ),
+ ## Explicit Format
+ (
+ 'Export["abc.txt", 1+x, "JPF"]',
+ ("{JPF} is not a valid set of export elements for the Text format.",),
+ "$Failed",
+ None,
+ ),
+ (
+ 'Export["abc.txt", 1+x, {"JPF"}]',
+ ("{JPF} is not a valid set of export elements for the Text format.",),
+ "$Failed",
+ None,
+ ),
+ ## Empty elems
+ ('Export["123.txt", 1+x, {}]', None, "123.txt", None),
+ (
+ 'Export["123.jcp", 1+x, {}]',
+ ("Cannot infer format of file 123.jcp.",),
+ "$Failed",
+ None,
+ ),
+ ## FORMATS
+ ## ASCII text
+ ('FileFormat["ExampleData/BloodToilTearsSweat.txt"]', None, "Text", None),
+ ('FileFormat["ExampleData/MadTeaParty.gif"]', None, "GIF", None),
+ ('FileFormat["ExampleData/moon.tif"]', None, "TIFF", None),
+ ('FileFormat["ExampleData/numberdata.csv"]', None, "CSV", None),
+ ('FileFormat["ExampleData/EinsteinSzilLetter.txt"]', None, "Text", None),
+ ('FileFormat["ExampleData/BloodToilTearsSweat.txt"]', None, "Text", None),
+ ('FileFormat["ExampleData/colors.json"]', None, "JSON", None),
+ (
+ 'FileFormat["ExampleData/some-typo.extension"]',
+ ("File not found during FileFormat[ExampleData/some-typo.extension].",),
+ "$Failed",
+ None,
+ ),
+ ('FileFormat["ExampleData/Testosterone.svg"]', None, "SVG", None),
+ ('FileFormat["ExampleData/colors.json"]', None, "JSON", None),
+ ('FileFormat["ExampleData/InventionNo1.xml"]', None, "XML", None),
+ ],
+)
+def test_private_doctests_importexport(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
+
+
# TODO:
# mmatera: please put in pytest conditionally
# >> System`Convert`B64Dump`B64Encode["∫ f x"]
diff --git a/test/builtin/numbers/test_algebra.py b/test/builtin/numbers/test_algebra.py
index 71f95cc4c..e1cbee3b3 100644
--- a/test/builtin/numbers/test_algebra.py
+++ b/test/builtin/numbers/test_algebra.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
"""
-Unit tests for mathics.builtins.numbers.algebra
+Unit tests for mathics.builtins.numbers.algebra and
+mathics.builtins.numbers.integer
"""
from test.helper import check_evaluation
@@ -329,3 +330,183 @@ def test_fullsimplify():
),
):
check_evaluation(str_expr, str_expected, failure_message)
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ ("Attributes[f] = {HoldAll}; Apart[f[x + x]]", None, "f[x + x]", None),
+ ("Attributes[f] = {}; Apart[f[x + x]]", None, "f[2 x]", None),
+ ## Errors:
+ (
+ "Coefficient[x + y + 3]",
+ ("Coefficient called with 1 argument; 2 or 3 arguments are expected.",),
+ "Coefficient[3 + x + y]",
+ None,
+ ),
+ (
+ "Coefficient[x + y + 3, 5]",
+ ("5 is not a valid variable.",),
+ "Coefficient[3 + x + y, 5]",
+ None,
+ ),
+ ## This is known bug of Sympy 1.0, next Sympy version will fix it by this commit
+ ## https://github.com/sympy/sympy/commit/25bf64b64d4d9a2dc563022818d29d06bc740d47
+ ("Coefficient[x * y, z, 0]", None, "x y", "Sympy 1.0 retuns 0"),
+ ## TODO: Support Modulus
+ # ("Coefficient[(x + 2)^3 + (x + 3)^2, x, 0, {Modulus -> 3, Modulus -> 2, Modulus -> 10}]",
+ # None,"{2, 1, 7}", None),
+ (
+ "CoefficientList[x + y, 5]",
+ ("5 is not a valid variable.",),
+ "CoefficientList[x + y, 5]",
+ None,
+ ),
+ (
+ "CoefficientList[(x - 2 y)^4, {x, 2}]",
+ ("2 is not a valid variable.",),
+ "CoefficientList[(x - 2 y) ^ 4, {x, 2}]",
+ None,
+ ),
+ (
+ "CoefficientList[x / y, {x, y}]",
+ ("x / y is not a polynomial.",),
+ "CoefficientList[x / y, {x, y}]",
+ None,
+ ),
+ ("Expand[x, Modulus -> -1] (* copy odd MMA behaviour *)", None, "0", None),
+ (
+ "Expand[x, Modulus -> x]",
+ ("Value of option Modulus -> x should be an integer.",),
+ "Expand[x, Modulus -> x]",
+ None,
+ ),
+ ("a(b(c+d)+e) // Expand", None, "a b c + a b d + a e", None),
+ ("(y^2)^(1/2)/(2x+2y)//Expand", None, "Sqrt[y ^ 2] / (2 x + 2 y)", None),
+ (
+ "2(3+2x)^2/(5+x^2+3x)^3 // Expand",
+ None,
+ "24 x / (5 + 3 x + x ^ 2) ^ 3 + 8 x ^ 2 / (5 + 3 x + x ^ 2) ^ 3 + 18 / (5 + 3 x + x ^ 2) ^ 3",
+ None,
+ ),
+ ## Modulus option
+ (
+ "ExpandDenominator[1 / (x + y)^3, Modulus -> 3]",
+ None,
+ "1 / (x ^ 3 + y ^ 3)",
+ None,
+ ),
+ (
+ "ExpandDenominator[1 / (x + y)^6, Modulus -> 4]",
+ None,
+ "1 / (x ^ 6 + 2 x ^ 5 y + 3 x ^ 4 y ^ 2 + 3 x ^ 2 y ^ 4 + 2 x y ^ 5 + y ^ 6)",
+ None,
+ ),
+ (
+ "ExpandDenominator[2(3+2x)^2/(5+x^2+3x)^3]",
+ None,
+ "2 (3 + 2 x) ^ 2 / (125 + 225 x + 210 x ^ 2 + 117 x ^ 3 + 42 x ^ 4 + 9 x ^ 5 + x ^ 6)",
+ None,
+ ),
+ ## errors:
+ (
+ "Exponent[x^2]",
+ ("Exponent called with 1 argument; 2 or 3 arguments are expected.",),
+ "Exponent[x ^ 2]",
+ None,
+ ),
+ ## Issue659
+ ("Factor[{x+x^2}]", None, "{x (1 + x)}", None),
+ ("FactorTermsList[2 x^2 - 2, x]", None, "{2, 1, -1 + x ^ 2}", None),
+ (
+ "MinimalPolynomial[7a, x]",
+ ("7 a is not an explicit algebraic number.",),
+ "MinimalPolynomial[7 a, x]",
+ None,
+ ),
+ (
+ "MinimalPolynomial[3x^3 + 2x^2 + y^2 + ab, x]",
+ ("ab + 2 x ^ 2 + 3 x ^ 3 + y ^ 2 is not an explicit algebraic number.",),
+ "MinimalPolynomial[ab + 2 x ^ 2 + 3 x ^ 3 + y ^ 2, x]",
+ None,
+ ),
+ ## PurePoly
+ ("MinimalPolynomial[Sqrt[2 + Sqrt[3]]]", None, "1 - 4 #1 ^ 2 + #1 ^ 4", None),
+ (
+ "PolynomialQ[x, x, y]",
+ ("PolynomialQ called with 3 arguments; 1 or 2 arguments are expected.",),
+ "PolynomialQ[x, x, y]",
+ None,
+ ),
+ ## Always return True if argument is Null
+ (
+ "PolynomialQ[x^3 - 2 x/y + 3xz, ]",
+ None,
+ "True",
+ "Always return True if argument is Null",
+ ),
+ (
+ "PolynomialQ[, {x, y, z}]",
+ None,
+ "True",
+ "True if the expression is Null",
+ ),
+ (
+ "PolynomialQ[, ]",
+ None,
+ "True",
+ None,
+ ),
+ ## TODO: MMA and Sympy handle these cases differently
+ ## #> PolynomialQ[x^(1/2) + 6xyz]
+ ## : No variable is not supported in PolynomialQ.
+ ## = True
+ ## #> PolynomialQ[x^(1/2) + 6xyz, {}]
+ ## : No variable is not supported in PolynomialQ.
+ ## = True
+ ## #> PolynomialQ[x^3 - 2 x/y + 3xz]
+ ## : No variable is not supported in PolynomialQ.
+ ## = False
+ ## #> PolynomialQ[x^3 - 2 x/y + 3xz, {}]
+ ## : No variable is not supported in PolynomialQ.
+ ## = False
+ ("f[x]/x+f[x]/x^2//Together", None, "f[x] (1 + x) / x ^ 2", None),
+ ## failing test case from MMA docs
+ ("Variables[E^x]", None, "{}", None),
+ ],
+)
+def test_private_doctests_algebra(str_expr, msgs, str_expected, fail_msg):
+ """doctests for algebra"""
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ (
+ "FromDigits[x]",
+ ("The input must be a string of digits or a list.",),
+ "FromDigits[x, 10]",
+ None,
+ ),
+ ],
+)
+def test_private_doctests_integer(str_expr, msgs, str_expected, fail_msg):
+ """doctests for integer"""
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/numbers/test_calculus.py b/test/builtin/numbers/test_calculus.py
index 7d4d3c60c..0230a8c7e 100644
--- a/test/builtin/numbers/test_calculus.py
+++ b/test/builtin/numbers/test_calculus.py
@@ -2,7 +2,7 @@
"""
Unit tests for mathics.builtins.numbers.calculus
-In parituclar:
+In partiuclar:
FindRoot[], FindMinimum[], NFindMaximum[] tests
@@ -226,3 +226,68 @@ def test_private_doctests_optimization(str_expr, msgs, str_expected, fail_msg):
failure_message=fail_msg,
expected_messages=msgs,
)
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ (
+ "D[2/3 Cos[x] - 1/3 x Cos[x] Sin[x] ^ 2,x]//Expand",
+ None,
+ "-2 x Cos[x] ^ 2 Sin[x] / 3 + x Sin[x] ^ 3 / 3 - 2 Sin[x] / 3 - Cos[x] Sin[x] ^ 2 / 3",
+ None,
+ ),
+ ("D[f[#1], {#1,2}]", None, "f''[#1]", None),
+ ("D[(#1&)[t],{t,4}]", None, "0", None),
+ ("Attributes[f] ={HoldAll}; Apart[f''[x + x]]", None, "f''[2 x]", None),
+ ("Attributes[f] = {}; Apart[f''[x + x]]", None, "f''[2 x]", None),
+ ## Issue #375
+ ("D[{#^2}, #]", None, "{2 #1}", None),
+ ("FindRoot[2.5==x,{x,0}]", None, "{x -> 2.5}", None),
+ ("DownValues[Integrate]", None, "{}", None),
+ (
+ "Definition[Integrate]",
+ None,
+ (
+ "Attributes[Integrate] = {Protected, ReadProtected}\n"
+ "\n"
+ "Options[Integrate] = {Assumptions -> $Assumptions, GenerateConditions -> Automatic, PrincipalValue -> False}\n"
+ ),
+ None,
+ ),
+ (
+ "Integrate[Hold[x + x], {x, a, b}]",
+ None,
+ "Integrate[Hold[x + x], {x, a, b}]",
+ None,
+ ),
+ ("Integrate[sin[x], x]", None, "Integrate[sin[x], x]", None),
+ ("Integrate[x ^ 3.5 + x, x]", None, "x ^ 2 / 2 + 0.222222 x ^ 4.5", None),
+ (
+ "Integrate[1/(x^5+1), x]",
+ None,
+ "RootSum[1 + 5 #1 + 25 #1 ^ 2 + 125 #1 ^ 3 + 625 #1 ^ 4&, Log[x + 5 #1] #1&] + Log[1 + x] / 5",
+ None,
+ ),
+ ("Integrate[ArcTan(x), x]", None, "x ^ 2 ArcTan / 2", None),
+ ("Integrate[E[x], x]", None, "Integrate[E[x], x]", None),
+ ("Integrate[Exp[-(x/2)^2],{x,-Infinity,+Infinity}]", None, "2 Sqrt[Pi]", None),
+ (
+ "Integrate[Exp[-1/(x^2)], x]",
+ None,
+ "x E ^ (-1 / x ^ 2) + Sqrt[Pi] Erf[1 / x]",
+ None,
+ ),
+ ],
+)
+def test_private_doctests_calculus(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/numbers/test_diffeqns.py b/test/builtin/numbers/test_diffeqns.py
new file mode 100644
index 000000000..46a8579d7
--- /dev/null
+++ b/test/builtin/numbers/test_diffeqns.py
@@ -0,0 +1,106 @@
+# -*- coding: utf-8 -*-
+"""
+Unit tests for mathics.builtins.numbers.diffeqns
+"""
+from test.helper import check_evaluation
+
+import pytest
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ ## FIXME: sympy solves this as `Function[{x}, C[1] + Integrate[ArcSin[f[2 x]], x]]`
+ # (
+ # "Attributes[f] = {HoldAll}; DSolve[f[x + x] == Sin[f'[x]], f, x]",
+ # (
+ # (
+ # "To avoid possible ambiguity, the arguments of the dependent "
+ # "variable in f[x + x] == Sin[f'[x]] should literally match "
+ # "the independent variables."
+ # ),
+ # ),
+ # "DSolve[f[x + x] == Sin[f'[x]], f, x]",
+ # "sympy solves this as `Function[{x}, C[1] + Integrate[ArcSin[f[2 x]], x]]`",
+ # ),
+ # """
+ # (
+ # "Attributes[f] = {}; DSolve[f[x + x] == Sin[f'[x]], f, x]",
+ # (
+ # (
+ # "To avoid possible ambiguity, the arguments of the dependent "
+ # "variable in f[2 x] == Sin[f'[x]] should literally match "
+ # "the independent variables."
+ # ),
+ # ),
+ # "DSolve[f[2 x] == Sin[f'[x]], f, x]",
+ # None,
+ # ),
+ (
+ "DSolve[f'[x] == f[x], f, x] // FullForm",
+ None,
+ "{{Rule[f, Function[{x}, Times[C[1], Power[E, x]]]]}}",
+ None,
+ ),
+ (
+ "DSolve[f'[x] == f[x], f, x] /. {C[1] -> 1}",
+ None,
+ "{{f -> (Function[{x}, 1 E ^ x])}}",
+ None,
+ ),
+ (
+ "DSolve[f'[x] == f[x], f, x] /. {C -> D}",
+ None,
+ "{{f -> (Function[{x}, D[1] E ^ x])}}",
+ None,
+ ),
+ (
+ "DSolve[f'[x] == f[x], f, x] /. {C[1] -> C[0]}",
+ None,
+ "{{f -> (Function[{x}, C[0] E ^ x])}}",
+ None,
+ ),
+ (
+ "DSolve[f[x] == 0, f, {}]",
+ ("{} cannot be used as a variable.",),
+ "DSolve[f[x] == 0, f, {}]",
+ None,
+ ),
+ ## Order of arguments shoudn't matter
+ (
+ "DSolve[D[f[x, y], x] == D[f[x, y], y], f, {x, y}]",
+ None,
+ "{{f -> (Function[{x, y}, C[1][-x - y]])}}",
+ None,
+ ),
+ (
+ "DSolve[D[f[x, y], x] == D[f[x, y], y], f[x, y], {x, y}]",
+ None,
+ "{{f[x, y] -> C[1][-x - y]}}",
+ None,
+ ),
+ (
+ "DSolve[D[f[x, y], x] == D[f[x, y], y], f[x, y], {y, x}]",
+ None,
+ "{{f[x, y] -> C[1][-x - y]}}",
+ None,
+ ),
+ (
+ "DSolve[\\[Gamma]'[x] == 0, \\[Gamma], x]",
+ None,
+ "{{γ -> (Function[{x}, C[1]])}}",
+ "sympy #11669 test",
+ ),
+ ],
+)
+def test_private_doctests_diffeqns(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/numbers/test_hyperbolic.py b/test/builtin/numbers/test_hyperbolic.py
index 762cab81f..5b7a4cc31 100644
--- a/test/builtin/numbers/test_hyperbolic.py
+++ b/test/builtin/numbers/test_hyperbolic.py
@@ -1,12 +1,15 @@
-# -*- coding: utf-8 -*-
+## -*- coding: utf-8 -*-
"""
-Unit tests for mathics.builtins.numbers.hyperbolic
+Unit tests for mathics.builtins.numbers.hyperbolic and
+mathics.builtins.numbers.exp
These simple verify various rules from
from symja_android_library/symja_android_library/rules/Gudermannian.m
"""
from test.helper import check_evaluation
+import pytest
+
def test_gudermannian():
for str_expr, str_expected in (
@@ -34,3 +37,53 @@ def test_complexexpand():
),
):
check_evaluation(str_expr, str_expected)
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ ("ArcCosh[1.4]", None, "0.867015", None),
+ (
+ "ArcCoth[0.000000000000000000000000000000000000000]",
+ None,
+ "1.57079632679489661923132169163975144210 I",
+ None,
+ ),
+ ],
+)
+def test_private_doctests_hyperbolic(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ ("Exp[1.*^20]", ("Overflow occurred in computation.",), "Overflow[]", None),
+ ("Log[1000] / Log[10] // Simplify", None, "3", None),
+ ("Log[1.4]", None, "0.336472", None),
+ ("Log[Exp[1.4]]", None, "1.4", None),
+ ("Log[-1.4]", None, "0.336472 + 3.14159 I", None),
+ ("N[Log[10], 30]", None, "2.30258509299404568401799145468", None),
+ ("LogisticSigmoid[I Pi]", None, "LogisticSigmoid[I Pi]", None),
+ ],
+)
+def test_private_doctests_exp(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/numbers/test_linalg.py b/test/builtin/numbers/test_linalg.py
index 73a914082..3494e65e2 100644
--- a/test/builtin/numbers/test_linalg.py
+++ b/test/builtin/numbers/test_linalg.py
@@ -88,3 +88,139 @@ def test_inverse(str_expr, str_expected, fail_msg, warnings):
check_evaluation(
str_expr, str_expected, failure_message="", expected_messages=warnings
)
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ (
+ "Eigenvalues[{{1, 0}, {0}}]",
+ (
+ "Argument {{1, 0}, {0}} at position 1 is not a non-empty rectangular matrix.",
+ ),
+ "Eigenvalues[{{1, 0}, {0}}]",
+ None,
+ ),
+ (
+ "Eigenvectors[{{-2, 1, -1}, {-3, 2, 1}, {-1, 1, 0}}]",
+ None,
+ "{{1, 7, 3}, {1, 1, 0}, {0, 0, 0}}",
+ None,
+ ),
+ ## Inconsistent system - ideally we'd print a different message
+ (
+ "LeastSquares[{{1, 1, 1}, {1, 1, 1}}, {1, 0}]",
+ ("Solving for underdetermined system not implemented.",),
+ "LeastSquares[{{1, 1, 1}, {1, 1, 1}}, {1, 0}]",
+ None,
+ ),
+ (
+ "LeastSquares[{1, {2}}, {1, 2}]",
+ ("Argument {1, {2}} at position 1 is not a non-empty rectangular matrix.",),
+ "LeastSquares[{1, {2}}, {1, 2}]",
+ None,
+ ),
+ (
+ "LeastSquares[{{1, 2}, {3, 4}}, {1, {2}}]",
+ ("Argument {1, {2}} at position 2 is not a non-empty rectangular matrix.",),
+ "LeastSquares[{{1, 2}, {3, 4}}, {1, {2}}]",
+ None,
+ ),
+ (
+ "LinearSolve[{1, {2}}, {1, 2}]",
+ ("Argument {1, {2}} at position 1 is not a non-empty rectangular matrix.",),
+ "LinearSolve[{1, {2}}, {1, 2}]",
+ None,
+ ),
+ (
+ "LinearSolve[{{1, 2}, {3, 4}}, {1, {2}}]",
+ ("Argument {1, {2}} at position 2 is not a non-empty rectangular matrix.",),
+ "LinearSolve[{{1, 2}, {3, 4}}, {1, {2}}]",
+ None,
+ ),
+ ("MatrixExp[{{a, 0}, {0, b}}]", None, "{{E ^ a, 0}, {0, E ^ b}}", None),
+ (
+ "MatrixExp[{{1, 0}, {0}}]",
+ (
+ "Argument {{1, 0}, {0}} at position 1 is not a non-empty rectangular matrix.",
+ ),
+ "MatrixExp[{{1, 0}, {0}}]",
+ None,
+ ),
+ (
+ "MatrixPower[{{0, x}, {0, 0}}, n]",
+ None,
+ "MatrixPower[{{0, x}, {0, 0}}, n]",
+ None,
+ ),
+ (
+ "MatrixPower[{{1, 0}, {0}}, 2]",
+ (
+ "Argument {{1, 0}, {0}} at position 1 is not a non-empty rectangular matrix.",
+ ),
+ "MatrixPower[{{1, 0}, {0}}, 2]",
+ None,
+ ),
+ (
+ "MatrixRank[{{1, 0}, {0}}]",
+ (
+ "Argument {{1, 0}, {0}} at position 1 is not a non-empty rectangular matrix.",
+ ),
+ "MatrixRank[{{1, 0}, {0}}]",
+ None,
+ ),
+ (
+ "NullSpace[{1, {2}}]",
+ ("Argument {1, {2}} at position 1 is not a non-empty rectangular matrix.",),
+ "NullSpace[{1, {2}}]",
+ None,
+ ),
+ (
+ "PseudoInverse[{1, {2}}]",
+ ("Argument {1, {2}} at position 1 is not a non-empty rectangular matrix.",),
+ "PseudoInverse[{1, {2}}]",
+ None,
+ ),
+ (
+ "QRDecomposition[{1, {2}}]",
+ ("Argument {1, {2}} at position 1 is not a non-empty rectangular matrix.",),
+ "QRDecomposition[{1, {2}}]",
+ None,
+ ),
+ (
+ "RowReduce[{{1, 0}, {0}}]",
+ (
+ "Argument {{1, 0}, {0}} at position 1 is not a non-empty rectangular matrix.",
+ ),
+ "RowReduce[{{1, 0}, {0}}]",
+ None,
+ ),
+ (
+ "SingularValueDecomposition[{{3/2, 2}, {5/2, 3}}]",
+ ("Symbolic SVD is not implemented, performing numerically.",),
+ (
+ "{{{0.538954, 0.842335}, {0.842335, -0.538954}}, "
+ "{{4.63555, 0.}, {0., 0.107862}}, "
+ "{{0.628678, 0.777666}, {-0.777666, 0.628678}}}"
+ ),
+ None,
+ ),
+ (
+ "SingularValueDecomposition[{1, {2}}]",
+ ("Argument {1, {2}} at position 1 is not a non-empty rectangular matrix.",),
+ "SingularValueDecomposition[{1, {2}}]",
+ None,
+ ),
+ ],
+)
+def test_private_doctests_linalg(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/numbers/test_numbertheory.py b/test/builtin/numbers/test_numbertheory.py
new file mode 100644
index 000000000..8e5e149b4
--- /dev/null
+++ b/test/builtin/numbers/test_numbertheory.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+"""
+Unit tests for mathics.builtins.numbers.numbertheory
+"""
+from test.helper import check_evaluation
+
+import pytest
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ ("Divisors[0]", None, "Divisors[0]", None),
+ (
+ "Divisors[{-206, -502, -1702, 9}]",
+ None,
+ (
+ "{{1, 2, 103, 206}, "
+ "{1, 2, 251, 502}, "
+ "{1, 2, 23, 37, 46, 74, 851, 1702}, "
+ "{1, 3, 9}}"
+ ),
+ None,
+ ),
+ ("Length[Divisors[1000*369]]", None, "96", None),
+ ("Length[Divisors[305*176*369*100]]", None, "672", None),
+ ("FractionalPart[b]", None, "FractionalPart[b]", None),
+ ("FractionalPart[{-2.4, -2.5, -3.0}]", None, "{-0.4, -0.5, 0.}", None),
+ ("FractionalPart[14/32]", None, "7 / 16", None),
+ ("FractionalPart[4/(1 + 3 I)]", None, "2 / 5 - I / 5", None),
+ ("FractionalPart[Pi^20]", None, "-8769956796 + Pi ^ 20", None),
+ ("MantissaExponent[E, Pi]", None, "{E / Pi, 1}", None),
+ ("MantissaExponent[Pi, Pi]", None, "{1 / Pi, 2}", None),
+ ("MantissaExponent[5/2 + 3, Pi]", None, "{11 / (2 Pi ^ 2), 2}", None),
+ ("MantissaExponent[b]", None, "MantissaExponent[b]", None),
+ ("MantissaExponent[17, E]", None, "{17 / E ^ 3, 3}", None),
+ ("MantissaExponent[17., E]", None, "{0.84638, 3}", None),
+ ("MantissaExponent[Exp[Pi], 2]", None, "{E ^ Pi / 32, 5}", None),
+ (
+ "MantissaExponent[3 + 2 I, 2]",
+ ("The value 3 + 2 I is not a real number",),
+ "MantissaExponent[3 + 2 I, 2]",
+ None,
+ ),
+ (
+ "MantissaExponent[25, 0.4]",
+ ("Base 0.4 is not a real number greater than 1.",),
+ "MantissaExponent[25, 0.4]",
+ None,
+ ),
+ ("MantissaExponent[0.0000124]", None, "{0.124, -4}", None),
+ ("MantissaExponent[0.0000124, 2]", None, "{0.812646, -16}", None),
+ ("MantissaExponent[0]", None, "{0, 0}", None),
+ ("MantissaExponent[0, 2]", None, "{0, 0}", None),
+ ("PrimePowerQ[1]", None, "False", None),
+ ("RandomPrime[{10,12}, {2,2}]", None, "{{11, 11}, {11, 11}}", None),
+ ("RandomPrime[2, {3,2}]", None, "{{2, 2}, {2, 2}, {2, 2}}", None),
+ ],
+)
+def test_private_doctests_numbertheory(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/numbers/test_randomnumbers.py b/test/builtin/numbers/test_randomnumbers.py
index d2bf37277..9e0e7bccd 100644
--- a/test/builtin/numbers/test_randomnumbers.py
+++ b/test/builtin/numbers/test_randomnumbers.py
@@ -39,3 +39,70 @@ def test_random_sample(str_expr, str_expected):
to_string_expr=True,
to_string_expected=True,
)
+
+
+# -*- coding: utf-8 -*-
+"""
+Unit tests for mathics.builtins.specialfns.gamma
+"""
+from test.helper import check_evaluation
+
+import pytest
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ (
+ "RandomComplex[] //(0 <= Re[#1] <= 1 && 0 <= Im[#1] <= 1)&",
+ None,
+ "True",
+ None,
+ ),
+ (
+ "z=RandomComplex[{1+I, 5+5I}];1 <= Re[z] <= 5 && 1 <= Im[z] <= 5",
+ None,
+ "True",
+ None,
+ ),
+ (
+ "z=.;RandomComplex[{6.3, 2.5 I}] // Head",
+ None,
+ "Complex",
+ None,
+ ),
+ ("RandomInteger[{1, 5}]// (1<= #1 <= 5)&", None, "True", None),
+ ("RandomReal[]// (0<= #1 <= 1)&", None, "True", None),
+ (
+ "Length /@ RandomReal[100, {2, 3}]",
+ None,
+ "{3, 3}",
+ None,
+ ),
+ (
+ "RandomReal[{0, 1}, {1, -1}]",
+ (
+ "The array dimensions {1, -1} given in position 2 of RandomReal[{0, 1}, {1, -1}] should be a list of non-negative machine-sized integers giving the dimensions for the result.",
+ ),
+ "RandomReal[{0, 1}, {1, -1}]",
+ None,
+ ),
+ (
+ "SeedRandom[x]",
+ ("Argument x should be an integer or string.",),
+ "SeedRandom[x]",
+ None,
+ ),
+ ],
+)
+def test_private_doctests_randomnumbers(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/numbers/test_trig.py b/test/builtin/numbers/test_trig.py
index 5aee15cb7..dbe01c2d4 100644
--- a/test/builtin/numbers/test_trig.py
+++ b/test/builtin/numbers/test_trig.py
@@ -7,6 +7,8 @@
"""
from test.helper import check_evaluation
+import pytest
+
def test_ArcCos():
for str_expr, str_expected in (
@@ -22,3 +24,31 @@ def test_ArcCos():
("ArcCos[(1 + Sqrt[3]) / (2*Sqrt[2])]", "1/12 Pi"),
):
check_evaluation(str_expr, str_expected)
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ ("ArcTan[-1, 1]", None, "3 Pi / 4", None),
+ ("ArcTan[1, -1]", None, "-Pi / 4", None),
+ ("ArcTan[-1, -1]", None, "-3 Pi / 4", None),
+ ("ArcTan[1, 0]", None, "0", None),
+ ("ArcTan[-1, 0]", None, "Pi", None),
+ ("ArcTan[0, 1]", None, "Pi / 2", None),
+ ("ArcTan[0, -1]", None, "-Pi / 2", None),
+ ("Cos[1.5 Pi]", None, "-1.83697×10^-16", None),
+ ("N[Sin[1], 40]", None, "0.8414709848078965066525023216302989996226", None),
+ ("Tan[0.5 Pi]", None, "1.63312×10^16", None),
+ ],
+)
+def test_private_doctests_trig(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/specialfns/test_bessel.py b/test/builtin/specialfns/test_bessel.py
index b6201d76e..77a73ee98 100644
--- a/test/builtin/specialfns/test_bessel.py
+++ b/test/builtin/specialfns/test_bessel.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
"""
-Unit tests for mathics.builtins.arithmetic.bessel
+Unit tests for mathics.builtins.specialfns.bessel and
+mathics.builtins.specialfns.orthogonal
"""
from test.helper import check_evaluation
@@ -13,7 +14,7 @@
# by SymPy.
[
(
- "BesselI[1/2,z]",
+ "z=.;BesselI[1/2,z]",
"Sqrt[2] Sinh[z] / (Sqrt[z] Sqrt[Pi])",
"BesselI 1/2 rule",
),
@@ -30,3 +31,64 @@ def test_add(str_expr, str_expected, assert_failure_msg):
check_evaluation(
str_expr, str_expected, hold_expected=True, failure_message=assert_failure_msg
)
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ ("AiryAiZero[1]", None, "AiryAiZero[1]", None),
+ ("AiryAiZero[1.]", None, "AiryAiZero[1.]", None),
+ ("AiryAi[AiryAiZero[1]]", None, "0", None),
+ (
+ "N[AiryAiZero[2], 100]",
+ None,
+ "-4.087949444130970616636988701457391060224764699108529754984160876025121946836047394331169160758270562",
+ None,
+ ),
+ ("AiryBiZero[1]", None, "AiryBiZero[1]", None),
+ ("AiryBiZero[1.]", None, "AiryBiZero[1.]", None),
+ ("AiryBi[AiryBiZero[1]]", None, "0", None),
+ (
+ "N[AiryBiZero[2], 100]",
+ None,
+ "-3.271093302836352715680228240166413806300935969100284801485032396261130864238742879252000673830055014",
+ None,
+ ),
+ ("BesselJ[2.5, 1]", None, "0.0494968", None),
+ ],
+)
+def test_private_doctests_bessel(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ (
+ "SphericalHarmonicY[1,1,x,y]",
+ None,
+ "-Sqrt[6] E ^ (I y) Sin[x] / (4 Sqrt[Pi])",
+ None,
+ ),
+ ],
+)
+def test_private_doctests_orthogonal(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/specialfns/test_gamma.py b/test/builtin/specialfns/test_gamma.py
new file mode 100644
index 000000000..b5d1d4148
--- /dev/null
+++ b/test/builtin/specialfns/test_gamma.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+"""
+Unit tests for mathics.builtins.specialfns.gamma
+"""
+from test.helper import check_evaluation
+
+import pytest
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ ("0!", None, "1", None),
+ (
+ "N[Gamma[24/10], 100]",
+ None,
+ "1.242169344504305404913070252268300492431517240992022966055507541481863694148882652446155342679460339",
+ "Issue 203",
+ ),
+ (
+ "res=N[N[Gamma[24/10],100]/N[Gamma[14/10],100],100]",
+ None,
+ "1.400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Issue 203",
+ ),
+ ("res // Precision", None, "100.", None),
+ (
+ "Gamma[1.*^20]",
+ ("Overflow occurred in computation.",),
+ "Overflow[]",
+ "Overflow",
+ ),
+ ("Gamma[1., 2.]", None, "Gamma[1., 2.]", "needs mpmath for lowergamma"),
+ ],
+)
+def test_private_doctests_gamma(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/test_intfns.py b/test/builtin/test_intfns.py
new file mode 100644
index 000000000..c7c790728
--- /dev/null
+++ b/test/builtin/test_intfns.py
@@ -0,0 +1,213 @@
+# -*- coding: utf-8 -*-
+"""
+Unit tests from mathics.builtin.intfns
+"""
+
+from test.helper import check_evaluation, session
+
+import pytest
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ ("HarmonicNumber[-1.5]", None, "0.613706", None),
+ ],
+)
+def test_private_doctests_recurrence(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ ## TODO should be ComplexInfinity but mpmath returns +inf
+ ("Binomial[-10, -3.5]", None, "Infinity", None),
+ ("Subsets[{}]", None, "{{}}", None),
+ ("Subsets[]", None, "Subsets[]", None),
+ (
+ "Subsets[{a, b, c}, 2.5]",
+ (
+ "Position 2 of Subsets[{a, b, c}, 2.5] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer.",
+ ),
+ "Subsets[{a, b, c}, 2.5]",
+ None,
+ ),
+ (
+ "Subsets[{a, b, c}, -1]",
+ (
+ "Position 2 of Subsets[{a, b, c}, -1] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer.",
+ ),
+ "Subsets[{a, b, c}, -1]",
+ None,
+ ),
+ (
+ "Subsets[{a, b, c}, {3, 4, 5, 6}]",
+ (
+ "Position 2 of Subsets[{a, b, c}, {3, 4, 5, 6}] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer.",
+ ),
+ "Subsets[{a, b, c}, {3, 4, 5, 6}]",
+ None,
+ ),
+ (
+ "Subsets[{a, b, c}, {-1, 2}]",
+ (
+ "Position 2 of Subsets[{a, b, c}, {-1, 2}] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer.",
+ ),
+ "Subsets[{a, b, c}, {-1, 2}]",
+ None,
+ ),
+ (
+ "Subsets[{a, b, c}, All]",
+ None,
+ "{{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}}",
+ None,
+ ),
+ (
+ "Subsets[{a, b, c}, Infinity]",
+ None,
+ "{{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}}",
+ None,
+ ),
+ (
+ "Subsets[{a, b, c}, ALL]",
+ (
+ "Position 2 of Subsets[{a, b, c}, ALL] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer.",
+ ),
+ "Subsets[{a, b, c}, ALL]",
+ None,
+ ),
+ (
+ "Subsets[{a, b, c}, {a}]",
+ (
+ "Position 2 of Subsets[{a, b, c}, {a}] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer.",
+ ),
+ "Subsets[{a, b, c}, {a}]",
+ None,
+ ),
+ (
+ "Subsets[{a, b, c}, {}]",
+ (
+ "Position 2 of Subsets[{a, b, c}, {}] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer.",
+ ),
+ "Subsets[{a, b, c}, {}]",
+ None,
+ ),
+ ("Subsets[{a, b}, 0]", None, "{{}}", None),
+ (
+ "Subsets[{1, 2}, x]",
+ (
+ "Position 2 of Subsets[{1, 2}, x] must be All, Infinity, a non-negative integer, or a List whose first element (required) is a non-negative integer, second element (optional) is a non-negative integer or Infinity, and third element (optional) is a nonzero integer.",
+ ),
+ "Subsets[{1, 2}, x]",
+ None,
+ ),
+ (
+ "Subsets[x]",
+ ("Nonatomic expression expected at position 1 in Subsets[x].",),
+ "Subsets[x]",
+ None,
+ ),
+ (
+ "Subsets[x, {1, 2}]",
+ ("Nonatomic expression expected at position 1 in Subsets[x, {1, 2}].",),
+ "Subsets[x, {1, 2}]",
+ None,
+ ),
+ (
+ "Subsets[x, {1, 2, 3}, {1, 3}]",
+ (
+ "Nonatomic expression expected at position 1 in Subsets[x, {1, 2, 3}, {1, 3}].",
+ ),
+ "Subsets[x, {1, 2, 3}, {1, 3}]",
+ None,
+ ),
+ (
+ "Subsets[a + b + c]",
+ None,
+ "{0, a, b, c, a + b, a + c, b + c, a + b + c}",
+ None,
+ ),
+ (
+ "Subsets[f[a, b, c]]",
+ None,
+ "{f[], f[a], f[b], f[c], f[a, b], f[a, c], f[b, c], f[a, b, c]}",
+ None,
+ ),
+ ("Subsets[a + b + c, {1, 3, 2}]", None, "{a, b, c, a + b + c}", None),
+ ("Subsets[a* b * c, All, {6}]", None, "{a c}", None),
+ (
+ "Subsets[{a, b, c}, {1, Infinity}]",
+ None,
+ "{{a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}}",
+ None,
+ ),
+ (
+ "Subsets[{a, b, c}, {1, Infinity, 2}]",
+ None,
+ "{{a}, {b}, {c}, {a, b, c}}",
+ None,
+ ),
+ ("Subsets[{a, b, c}, {3, Infinity, -1}]", None, "{}", None),
+ ],
+)
+def test_private_doctests_combinatorial(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ (
+ "Quotient[13, 0]",
+ ("Infinite expression Quotient[13, 0] encountered.",),
+ "ComplexInfinity",
+ None,
+ ),
+ ("Quotient[-17, 7]", None, "-3", None),
+ ("Quotient[-17, -4]", None, "4", None),
+ ("Quotient[19, -4]", None, "-5", None),
+ (
+ "QuotientRemainder[13, 0]",
+ ("The argument 0 in QuotientRemainder[13, 0] should be nonzero.",),
+ "QuotientRemainder[13, 0]",
+ None,
+ ),
+ ("QuotientRemainder[-17, 7]", None, "{-3, 4}", None),
+ ("QuotientRemainder[-17, -4]", None, "{4, -1}", None),
+ ("QuotientRemainder[19, -4]", None, "{-5, -1}", None),
+ ("QuotientRemainder[a, 0]", None, "QuotientRemainder[a, 0]", None),
+ ("QuotientRemainder[a, b]", None, "QuotientRemainder[a, b]", None),
+ ("QuotientRemainder[5.2,2.5]", None, "{2, 0.2}", None),
+ ("QuotientRemainder[5, 2.]", None, "{2, 1.}", None),
+ ],
+)
+def test_private_doctests_divlike(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/builtin/test_numeric.py b/test/builtin/test_numeric.py
index dff0d72b9..ae5e6c603 100644
--- a/test/builtin/test_numeric.py
+++ b/test/builtin/test_numeric.py
@@ -4,9 +4,10 @@
In particular, Rationalize and RealValuNumberQ
"""
-
from test.helper import check_evaluation
+import pytest
+
def test_rationalize():
# Some of the Rationalize tests were taken from Symja's tests and docs
@@ -67,3 +68,73 @@ def test_realvalued():
),
):
check_evaluation(str_expr, str_expected)
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ (
+ "p=N[Pi,100]",
+ None,
+ "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068",
+ None,
+ ),
+ (
+ "ToString[p]",
+ None,
+ "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068",
+ None,
+ ),
+ ("N[1.012345678901234567890123, 20]", None, "1.0123456789012345679", None),
+ ("N[I, 30]", None, "1.00000000000000000000000000000 I", None),
+ (
+ "N[1.012345678901234567890123, 50] //{#1, #1//Precision}&",
+ None,
+ "{1.01234567890123456789012, 24.}",
+ None,
+ ),
+ (
+ "p=.;x=.;y=.;Rationalize[N[Pi] + 0.8 I, x]",
+ ("Tolerance specification x must be a non-negative number.",),
+ "Rationalize[3.14159 + 0.8 I, x]",
+ None,
+ ),
+ (
+ "Rationalize[N[Pi] + 0.8 I, -1]",
+ ("Tolerance specification -1 must be a non-negative number.",),
+ "Rationalize[3.14159 + 0.8 I, -1]",
+ None,
+ ),
+ (
+ "Rationalize[x, y]",
+ ("Tolerance specification y must be a non-negative number.",),
+ "Rationalize[x, y]",
+ None,
+ ),
+ (
+ "Sign[{1, 2.3, 4/5, {-6.7, 0}, {8/9, -10}}]",
+ None,
+ "{1, 1, 1, {-1, 0}, {1, -1}}",
+ None,
+ ),
+ ("Sign[1 - 4*I] == (1/17 - 4 I/17) Sqrt[17]", None, "True", None),
+ (
+ "Sign[4, 5, 6]",
+ ("Sign called with 3 arguments; 1 argument is expected.",),
+ "Sign[4, 5, 6]",
+ None,
+ ),
+ ('Sign["20"]', None, "Sign[20]", None),
+ ],
+)
+def test_private_doctests_numeric(str_expr, msgs, str_expected, fail_msg):
+ """ """
+ check_evaluation(
+ str_expr,
+ str_expected,
+ to_string_expr=True,
+ to_string_expected=True,
+ hold_expected=True,
+ failure_message=fail_msg,
+ expected_messages=msgs,
+ )
diff --git a/test/core/parser/test_parser.py b/test/core/parser/test_parser.py
index 2b9c33e60..026599044 100644
--- a/test/core/parser/test_parser.py
+++ b/test/core/parser/test_parser.py
@@ -291,6 +291,8 @@ def testDerivative(self):
self.check("f'", "Derivative[1][f]")
self.check("f''", "Derivative[2][f]")
self.check("f' '", "Derivative[2][f]")
+ self.check("f '' ''", "Derivative[4][f]")
+ self.check("Derivative[x][4] '", "Derivative[1][Derivative[x][4]]")
def testPlus(self):
self.check("+1", Node("Plus", Number("1")))
diff --git a/test/package/test_vectoranalysis.py b/test/package/test_vectoranalysis.py
new file mode 100644
index 000000000..c4648b481
--- /dev/null
+++ b/test/package/test_vectoranalysis.py
@@ -0,0 +1,122 @@
+# -*- coding: utf-8 -*-
+"""
+Unit tests from packages/VectorAnalysis
+"""
+import os.path as osp
+import sys
+from test.helper import check_evaluation, evaluate
+
+import pytest
+
+
+@pytest.mark.parametrize(
+ ("str_expr", "msgs", "str_expected", "fail_msg"),
+ [
+ (None, None, None, None),
+ ('Needs["VectorAnalysis`"];', None, "Null", None),
+ ("DotProduct[{1,2,3}, {4,5,6}]", None, "32", None),
+ ("DotProduct[{-1.4, 0.6, 0.2}, {0.1, 0.6, 1.7}]", None, "0.56", None),
+ ("CrossProduct[{1,2,3}, {4,5,6}]", None, "{-3, 6, -3}", None),
+ (
+ "CrossProduct[{-1.4, 0.6, 0.2}, {0.1, 0.6, 1.7}]",
+ None,
+ "{0.9, 2.4, -0.9}",
+ None,
+ ),
+ ("ScalarTripleProduct[{-2,3,1},{0,4,0},{-1,3,3}]", None, "-20", None),
+ (
+ "ScalarTripleProduct[{-1.4,0.6,0.2}, {0.1,0.6,1.7}, {0.7,-1.5,-0.2}]",
+ None,
+ "-2.79",
+ None,
+ ),
+ (
+ "last=CoordinatesToCartesian[{2, Pi, 3}, Spherical]",
+ None,
+ "{0, 0, -2}",
+ None,
+ ),
+ ("CoordinatesFromCartesian[last, Spherical]", None, "{2, Pi, 0}", None),
+ (
+ "last=CoordinatesToCartesian[{2, Pi, 3}, Cylindrical]",
+ None,
+ "{-2, 0, 3}",
+ None,
+ ),
+ ("CoordinatesFromCartesian[last, Cylindrical]", None, "{2, Pi, 3}", None),
+ ## Needs Sin/Cos exact value (PR #100) for these tests to pass
+ # ('last=CoordinatesToCartesian[{2, Pi / 4, Pi / 3}, Spherical]', None,
+ # '{Sqrt[2] / 2, Sqrt[2] Sqrt[3] / 2, Sqrt[2]}', None),
+ # ('CoordinatesFromCartesian[last, Spherical]', None,
+ # '{2, Pi / 4, Pi / 3}', None,),
+ # ('last=CoordinatesToCartesian[{2, Pi / 4, -1}, Cylindrical]', None,
+ # '{Sqrt[2], Sqrt[2], -1}', None),
+ # ('last=CoordinatesFromCartesian[last, Cylindrical]', None,
+ # '{2, Pi / 4, -1}', None),
+ ## Continue...
+ (
+ "CoordinatesToCartesian[{0.27, 0.51, 0.92}, Cylindrical]",
+ None,
+ "{0.235641, 0.131808, 0.92}",
+ None,
+ ),
+ (
+ "CoordinatesToCartesian[{0.27, 0.51, 0.92}, Spherical]",
+ None,
+ "{0.0798519, 0.104867, 0.235641}",
+ None,
+ ),
+ ("Coordinates[]", None, "{Xx, Yy, Zz}", None),
+ ("Coordinates[Spherical]", None, "{Rr, Ttheta, Pphi}", None),
+ ("SetCoordinates[Cylindrical]", None, "Cylindrical[Rr, Ttheta, Zz]", None),
+ ("Coordinates[]", None, "{Rr, Ttheta, Zz}", None),
+ ("CoordinateSystem", None, "Cylindrical", None),
+ ("Parameters[]", None, "{}", None),
+ (
+ "CoordinateRanges[]",
+ None,
+ ## And[a