From 8265c30a47a3e3416758bca18b4d5f15a578e522 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 9 Sep 2023 23:18:38 -0300 Subject: [PATCH 1/2] move private doctests to pytests in mathics.builtin.numbers --- mathics/builtin/numbers/algebra.py | 117 ------------- mathics/builtin/numbers/calculus.py | 60 ------- mathics/builtin/numbers/diffeqns.py | 42 ----- mathics/builtin/numbers/exp.py | 21 --- mathics/builtin/numbers/hyperbolic.py | 5 - mathics/builtin/numbers/integer.py | 4 - mathics/builtin/numbers/randomnumbers.py | 29 ---- mathics/builtin/numbers/trig.py | 24 --- test/builtin/numbers/test_algebra.py | 183 ++++++++++++++++++++- test/builtin/numbers/test_calculus.py | 67 +++++++- test/builtin/numbers/test_hyperbolic.py | 57 ++++++- test/builtin/numbers/test_randomnumbers.py | 67 ++++++++ test/builtin/numbers/test_trig.py | 30 ++++ test/builtin/specialfns/test_bessel.py | 2 +- test/core/parser/test_parser.py | 2 + 15 files changed, 403 insertions(+), 307 deletions(-) diff --git a/mathics/builtin/numbers/algebra.py b/mathics/builtin/numbers/algebra.py index 3ea0052d9..9af31c295 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 987d201a0..5bc6653f5 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 @@ -864,12 +836,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 = { @@ -970,20 +938,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. @@ -992,20 +946,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/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/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_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_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 6b7296763..77a73ee98 100644 --- a/test/builtin/specialfns/test_bessel.py +++ b/test/builtin/specialfns/test_bessel.py @@ -14,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", ), diff --git a/test/core/parser/test_parser.py b/test/core/parser/test_parser.py index 293a6675d..475e3bff6 100644 --- a/test/core/parser/test_parser.py +++ b/test/core/parser/test_parser.py @@ -282,6 +282,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"))) From 0d0ba213af64c3f1539bea1d76c8b69d68e9ab6c Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 9 Sep 2023 23:20:51 -0300 Subject: [PATCH 2/2] missing pytest --- test/builtin/numbers/test_diffeqns.py | 106 ++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 test/builtin/numbers/test_diffeqns.py 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, + )