ZhengyangZhang commited on
Commit
0cd2a8b
·
verified ·
1 Parent(s): e42f0f9

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. lib/python3.12/site-packages/sympy/assumptions/__pycache__/__init__.cpython-312.pyc +0 -0
  2. lib/python3.12/site-packages/sympy/assumptions/__pycache__/ask.cpython-312.pyc +0 -0
  3. lib/python3.12/site-packages/sympy/assumptions/__pycache__/ask_generated.cpython-312.pyc +0 -0
  4. lib/python3.12/site-packages/sympy/assumptions/__pycache__/assume.cpython-312.pyc +0 -0
  5. lib/python3.12/site-packages/sympy/assumptions/__pycache__/cnf.cpython-312.pyc +0 -0
  6. lib/python3.12/site-packages/sympy/assumptions/__pycache__/facts.cpython-312.pyc +0 -0
  7. lib/python3.12/site-packages/sympy/assumptions/__pycache__/lra_satask.cpython-312.pyc +0 -0
  8. lib/python3.12/site-packages/sympy/assumptions/__pycache__/refine.cpython-312.pyc +0 -0
  9. lib/python3.12/site-packages/sympy/assumptions/__pycache__/satask.cpython-312.pyc +0 -0
  10. lib/python3.12/site-packages/sympy/assumptions/__pycache__/sathandlers.cpython-312.pyc +0 -0
  11. lib/python3.12/site-packages/sympy/assumptions/handlers/__init__.py +13 -0
  12. lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/__init__.cpython-312.pyc +0 -0
  13. lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/calculus.cpython-312.pyc +0 -0
  14. lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/common.cpython-312.pyc +0 -0
  15. lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/matrices.cpython-312.pyc +0 -0
  16. lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/ntheory.cpython-312.pyc +0 -0
  17. lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/order.cpython-312.pyc +0 -0
  18. lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/sets.cpython-312.pyc +0 -0
  19. lib/python3.12/site-packages/sympy/assumptions/handlers/common.py +156 -0
  20. lib/python3.12/site-packages/sympy/assumptions/predicates/__init__.py +5 -0
  21. lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/__init__.cpython-312.pyc +0 -0
  22. lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/calculus.cpython-312.pyc +0 -0
  23. lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/common.cpython-312.pyc +0 -0
  24. lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/matrices.cpython-312.pyc +0 -0
  25. lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/ntheory.cpython-312.pyc +0 -0
  26. lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/order.cpython-312.pyc +0 -0
  27. lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/sets.cpython-312.pyc +0 -0
  28. lib/python3.12/site-packages/sympy/assumptions/predicates/calculus.py +82 -0
  29. lib/python3.12/site-packages/sympy/assumptions/predicates/common.py +81 -0
  30. lib/python3.12/site-packages/sympy/assumptions/predicates/matrices.py +511 -0
  31. lib/python3.12/site-packages/sympy/assumptions/predicates/ntheory.py +126 -0
  32. lib/python3.12/site-packages/sympy/assumptions/predicates/order.py +390 -0
  33. lib/python3.12/site-packages/sympy/assumptions/predicates/sets.py +399 -0
  34. lib/python3.12/site-packages/sympy/parsing/__pycache__/__init__.cpython-312.pyc +0 -0
  35. lib/python3.12/site-packages/sympy/parsing/__pycache__/ast_parser.cpython-312.pyc +0 -0
  36. lib/python3.12/site-packages/sympy/parsing/__pycache__/mathematica.cpython-312.pyc +0 -0
  37. lib/python3.12/site-packages/sympy/parsing/__pycache__/maxima.cpython-312.pyc +0 -0
  38. lib/python3.12/site-packages/sympy/parsing/c/__init__.py +1 -0
  39. lib/python3.12/site-packages/sympy/parsing/c/__pycache__/__init__.cpython-312.pyc +0 -0
  40. lib/python3.12/site-packages/sympy/parsing/c/__pycache__/c_parser.cpython-312.pyc +0 -0
  41. lib/python3.12/site-packages/sympy/parsing/c/c_parser.py +1058 -0
  42. lib/python3.12/site-packages/sympy/parsing/latex/LICENSE.txt +21 -0
  43. lib/python3.12/site-packages/sympy/parsing/latex/LaTeX.g4 +312 -0
  44. lib/python3.12/site-packages/sympy/parsing/latex/__init__.py +66 -0
  45. lib/python3.12/site-packages/sympy/parsing/latex/__pycache__/__init__.cpython-312.pyc +0 -0
  46. lib/python3.12/site-packages/sympy/parsing/latex/__pycache__/_build_latex_antlr.cpython-312.pyc +0 -0
  47. lib/python3.12/site-packages/sympy/parsing/latex/__pycache__/_parse_latex_antlr.cpython-312.pyc +0 -0
  48. lib/python3.12/site-packages/sympy/parsing/latex/__pycache__/errors.cpython-312.pyc +0 -0
  49. lib/python3.12/site-packages/sympy/parsing/latex/_antlr/__init__.py +9 -0
  50. lib/python3.12/site-packages/sympy/parsing/latex/_antlr/__pycache__/__init__.cpython-312.pyc +0 -0
lib/python3.12/site-packages/sympy/assumptions/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (727 Bytes). View file
 
lib/python3.12/site-packages/sympy/assumptions/__pycache__/ask.cpython-312.pyc ADDED
Binary file (24.5 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/__pycache__/ask_generated.cpython-312.pyc ADDED
Binary file (53.5 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/__pycache__/assume.cpython-312.pyc ADDED
Binary file (18.5 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/__pycache__/cnf.cpython-312.pyc ADDED
Binary file (23.7 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/__pycache__/facts.cpython-312.pyc ADDED
Binary file (14.9 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/__pycache__/lra_satask.cpython-312.pyc ADDED
Binary file (12.1 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/__pycache__/refine.cpython-312.pyc ADDED
Binary file (16 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/__pycache__/satask.cpython-312.pyc ADDED
Binary file (13.5 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/__pycache__/sathandlers.cpython-312.pyc ADDED
Binary file (17.1 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/handlers/__init__.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Multipledispatch handlers for ``Predicate`` are implemented here.
3
+ Handlers in this module are not directly imported to other modules in
4
+ order to avoid circular import problem.
5
+ """
6
+
7
+ from .common import (AskHandler, CommonHandler,
8
+ test_closed_group)
9
+
10
+ __all__ = [
11
+ 'AskHandler', 'CommonHandler',
12
+ 'test_closed_group'
13
+ ]
lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (529 Bytes). View file
 
lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/calculus.cpython-312.pyc ADDED
Binary file (8.94 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/common.cpython-312.pyc ADDED
Binary file (6.7 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/matrices.cpython-312.pyc ADDED
Binary file (39.8 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/ntheory.cpython-312.pyc ADDED
Binary file (11.3 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/order.cpython-312.pyc ADDED
Binary file (21.1 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/handlers/__pycache__/sets.cpython-312.pyc ADDED
Binary file (36.1 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/handlers/common.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This module defines base class for handlers and some core handlers:
3
+ ``Q.commutative`` and ``Q.is_true``.
4
+ """
5
+
6
+ from sympy.assumptions import Q, ask, AppliedPredicate
7
+ from sympy.core import Basic, Symbol
8
+ from sympy.core.logic import _fuzzy_group
9
+ from sympy.core.numbers import NaN, Number
10
+ from sympy.logic.boolalg import (And, BooleanTrue, BooleanFalse, conjuncts,
11
+ Equivalent, Implies, Not, Or)
12
+ from sympy.utilities.exceptions import sympy_deprecation_warning
13
+
14
+ from ..predicates.common import CommutativePredicate, IsTruePredicate
15
+
16
+
17
+ class AskHandler:
18
+ """Base class that all Ask Handlers must inherit."""
19
+ def __new__(cls, *args, **kwargs):
20
+ sympy_deprecation_warning(
21
+ """
22
+ The AskHandler system is deprecated. The AskHandler class should
23
+ be replaced with the multipledispatch handler of Predicate
24
+ """,
25
+ deprecated_since_version="1.8",
26
+ active_deprecations_target='deprecated-askhandler',
27
+ )
28
+ return super().__new__(cls, *args, **kwargs)
29
+
30
+
31
+ class CommonHandler(AskHandler):
32
+ # Deprecated
33
+ """Defines some useful methods common to most Handlers. """
34
+
35
+ @staticmethod
36
+ def AlwaysTrue(expr, assumptions):
37
+ return True
38
+
39
+ @staticmethod
40
+ def AlwaysFalse(expr, assumptions):
41
+ return False
42
+
43
+ @staticmethod
44
+ def AlwaysNone(expr, assumptions):
45
+ return None
46
+
47
+ NaN = AlwaysFalse
48
+
49
+
50
+ # CommutativePredicate
51
+
52
+ @CommutativePredicate.register(Symbol)
53
+ def _(expr, assumptions):
54
+ """Objects are expected to be commutative unless otherwise stated"""
55
+ assumps = conjuncts(assumptions)
56
+ if expr.is_commutative is not None:
57
+ return expr.is_commutative and not ~Q.commutative(expr) in assumps
58
+ if Q.commutative(expr) in assumps:
59
+ return True
60
+ elif ~Q.commutative(expr) in assumps:
61
+ return False
62
+ return True
63
+
64
+ @CommutativePredicate.register(Basic)
65
+ def _(expr, assumptions):
66
+ for arg in expr.args:
67
+ if not ask(Q.commutative(arg), assumptions):
68
+ return False
69
+ return True
70
+
71
+ @CommutativePredicate.register(Number)
72
+ def _(expr, assumptions):
73
+ return True
74
+
75
+ @CommutativePredicate.register(NaN)
76
+ def _(expr, assumptions):
77
+ return True
78
+
79
+
80
+ # IsTruePredicate
81
+
82
+ @IsTruePredicate.register(bool)
83
+ def _(expr, assumptions):
84
+ return expr
85
+
86
+ @IsTruePredicate.register(BooleanTrue)
87
+ def _(expr, assumptions):
88
+ return True
89
+
90
+ @IsTruePredicate.register(BooleanFalse)
91
+ def _(expr, assumptions):
92
+ return False
93
+
94
+ @IsTruePredicate.register(AppliedPredicate)
95
+ def _(expr, assumptions):
96
+ return ask(expr, assumptions)
97
+
98
+ @IsTruePredicate.register(Not)
99
+ def _(expr, assumptions):
100
+ arg = expr.args[0]
101
+ if arg.is_Symbol:
102
+ # symbol used as abstract boolean object
103
+ return None
104
+ value = ask(arg, assumptions=assumptions)
105
+ if value in (True, False):
106
+ return not value
107
+ else:
108
+ return None
109
+
110
+ @IsTruePredicate.register(Or)
111
+ def _(expr, assumptions):
112
+ result = False
113
+ for arg in expr.args:
114
+ p = ask(arg, assumptions=assumptions)
115
+ if p is True:
116
+ return True
117
+ if p is None:
118
+ result = None
119
+ return result
120
+
121
+ @IsTruePredicate.register(And)
122
+ def _(expr, assumptions):
123
+ result = True
124
+ for arg in expr.args:
125
+ p = ask(arg, assumptions=assumptions)
126
+ if p is False:
127
+ return False
128
+ if p is None:
129
+ result = None
130
+ return result
131
+
132
+ @IsTruePredicate.register(Implies)
133
+ def _(expr, assumptions):
134
+ p, q = expr.args
135
+ return ask(~p | q, assumptions=assumptions)
136
+
137
+ @IsTruePredicate.register(Equivalent)
138
+ def _(expr, assumptions):
139
+ p, q = expr.args
140
+ pt = ask(p, assumptions=assumptions)
141
+ if pt is None:
142
+ return None
143
+ qt = ask(q, assumptions=assumptions)
144
+ if qt is None:
145
+ return None
146
+ return pt == qt
147
+
148
+
149
+ #### Helper methods
150
+ def test_closed_group(expr, assumptions, key):
151
+ """
152
+ Test for membership in a group with respect
153
+ to the current operation.
154
+ """
155
+ return _fuzzy_group(
156
+ (ask(key(a), assumptions) for a in expr.args), quick_exit=True)
lib/python3.12/site-packages/sympy/assumptions/predicates/__init__.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ """
2
+ Module to implement predicate classes.
3
+
4
+ Class of every predicate registered to ``Q`` is defined here.
5
+ """
lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (327 Bytes). View file
 
lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/calculus.cpython-312.pyc ADDED
Binary file (2.54 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/common.cpython-312.pyc ADDED
Binary file (3.16 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/matrices.cpython-312.pyc ADDED
Binary file (14.4 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/ntheory.cpython-312.pyc ADDED
Binary file (3.24 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/order.cpython-312.pyc ADDED
Binary file (10.9 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/predicates/__pycache__/sets.cpython-312.pyc ADDED
Binary file (10.5 kB). View file
 
lib/python3.12/site-packages/sympy/assumptions/predicates/calculus.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.assumptions import Predicate
2
+ from sympy.multipledispatch import Dispatcher
3
+
4
+ class FinitePredicate(Predicate):
5
+ """
6
+ Finite number predicate.
7
+
8
+ Explanation
9
+ ===========
10
+
11
+ ``Q.finite(x)`` is true if ``x`` is a number but neither an infinity
12
+ nor a ``NaN``. In other words, ``ask(Q.finite(x))`` is true for all
13
+ numerical ``x`` having a bounded absolute value.
14
+
15
+ Examples
16
+ ========
17
+
18
+ >>> from sympy import Q, ask, S, oo, I, zoo
19
+ >>> from sympy.abc import x
20
+ >>> ask(Q.finite(oo))
21
+ False
22
+ >>> ask(Q.finite(-oo))
23
+ False
24
+ >>> ask(Q.finite(zoo))
25
+ False
26
+ >>> ask(Q.finite(1))
27
+ True
28
+ >>> ask(Q.finite(2 + 3*I))
29
+ True
30
+ >>> ask(Q.finite(x), Q.positive(x))
31
+ True
32
+ >>> print(ask(Q.finite(S.NaN)))
33
+ None
34
+
35
+ References
36
+ ==========
37
+
38
+ .. [1] https://en.wikipedia.org/wiki/Finite
39
+
40
+ """
41
+ name = 'finite'
42
+ handler = Dispatcher(
43
+ "FiniteHandler",
44
+ doc=("Handler for Q.finite. Test that an expression is bounded respect"
45
+ " to all its variables.")
46
+ )
47
+
48
+
49
+ class InfinitePredicate(Predicate):
50
+ """
51
+ Infinite number predicate.
52
+
53
+ ``Q.infinite(x)`` is true iff the absolute value of ``x`` is
54
+ infinity.
55
+
56
+ """
57
+ # TODO: Add examples
58
+ name = 'infinite'
59
+ handler = Dispatcher(
60
+ "InfiniteHandler",
61
+ doc="""Handler for Q.infinite key."""
62
+ )
63
+
64
+
65
+ class PositiveInfinitePredicate(Predicate):
66
+ """
67
+ Positive infinity predicate.
68
+
69
+ ``Q.positive_infinite(x)`` is true iff ``x`` is positive infinity ``oo``.
70
+ """
71
+ name = 'positive_infinite'
72
+ handler = Dispatcher("PositiveInfiniteHandler")
73
+
74
+
75
+ class NegativeInfinitePredicate(Predicate):
76
+ """
77
+ Negative infinity predicate.
78
+
79
+ ``Q.negative_infinite(x)`` is true iff ``x`` is negative infinity ``-oo``.
80
+ """
81
+ name = 'negative_infinite'
82
+ handler = Dispatcher("NegativeInfiniteHandler")
lib/python3.12/site-packages/sympy/assumptions/predicates/common.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.assumptions import Predicate, AppliedPredicate, Q
2
+ from sympy.core.relational import Eq, Ne, Gt, Lt, Ge, Le
3
+ from sympy.multipledispatch import Dispatcher
4
+
5
+
6
+ class CommutativePredicate(Predicate):
7
+ """
8
+ Commutative predicate.
9
+
10
+ Explanation
11
+ ===========
12
+
13
+ ``ask(Q.commutative(x))`` is true iff ``x`` commutes with any other
14
+ object with respect to multiplication operation.
15
+
16
+ """
17
+ # TODO: Add examples
18
+ name = 'commutative'
19
+ handler = Dispatcher("CommutativeHandler", doc="Handler for key 'commutative'.")
20
+
21
+
22
+ binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le}
23
+
24
+ class IsTruePredicate(Predicate):
25
+ """
26
+ Generic predicate.
27
+
28
+ Explanation
29
+ ===========
30
+
31
+ ``ask(Q.is_true(x))`` is true iff ``x`` is true. This only makes
32
+ sense if ``x`` is a boolean object.
33
+
34
+ Examples
35
+ ========
36
+
37
+ >>> from sympy import ask, Q
38
+ >>> from sympy.abc import x, y
39
+ >>> ask(Q.is_true(True))
40
+ True
41
+
42
+ Wrapping another applied predicate just returns the applied predicate.
43
+
44
+ >>> Q.is_true(Q.even(x))
45
+ Q.even(x)
46
+
47
+ Wrapping binary relation classes in SymPy core returns applied binary
48
+ relational predicates.
49
+
50
+ >>> from sympy import Eq, Gt
51
+ >>> Q.is_true(Eq(x, y))
52
+ Q.eq(x, y)
53
+ >>> Q.is_true(Gt(x, y))
54
+ Q.gt(x, y)
55
+
56
+ Notes
57
+ =====
58
+
59
+ This class is designed to wrap the boolean objects so that they can
60
+ behave as if they are applied predicates. Consequently, wrapping another
61
+ applied predicate is unnecessary and thus it just returns the argument.
62
+ Also, binary relation classes in SymPy core have binary predicates to
63
+ represent themselves and thus wrapping them with ``Q.is_true`` converts them
64
+ to these applied predicates.
65
+
66
+ """
67
+ name = 'is_true'
68
+ handler = Dispatcher(
69
+ "IsTrueHandler",
70
+ doc="Wrapper allowing to query the truth value of a boolean expression."
71
+ )
72
+
73
+ def __call__(self, arg):
74
+ # No need to wrap another predicate
75
+ if isinstance(arg, AppliedPredicate):
76
+ return arg
77
+ # Convert relational predicates instead of wrapping them
78
+ if getattr(arg, "is_Relational", False):
79
+ pred = binrelpreds[type(arg)]
80
+ return pred(*arg.args)
81
+ return super().__call__(arg)
lib/python3.12/site-packages/sympy/assumptions/predicates/matrices.py ADDED
@@ -0,0 +1,511 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.assumptions import Predicate
2
+ from sympy.multipledispatch import Dispatcher
3
+
4
+ class SquarePredicate(Predicate):
5
+ """
6
+ Square matrix predicate.
7
+
8
+ Explanation
9
+ ===========
10
+
11
+ ``Q.square(x)`` is true iff ``x`` is a square matrix. A square matrix
12
+ is a matrix with the same number of rows and columns.
13
+
14
+ Examples
15
+ ========
16
+
17
+ >>> from sympy import Q, ask, MatrixSymbol, ZeroMatrix, Identity
18
+ >>> X = MatrixSymbol('X', 2, 2)
19
+ >>> Y = MatrixSymbol('X', 2, 3)
20
+ >>> ask(Q.square(X))
21
+ True
22
+ >>> ask(Q.square(Y))
23
+ False
24
+ >>> ask(Q.square(ZeroMatrix(3, 3)))
25
+ True
26
+ >>> ask(Q.square(Identity(3)))
27
+ True
28
+
29
+ References
30
+ ==========
31
+
32
+ .. [1] https://en.wikipedia.org/wiki/Square_matrix
33
+
34
+ """
35
+ name = 'square'
36
+ handler = Dispatcher("SquareHandler", doc="Handler for Q.square.")
37
+
38
+
39
+ class SymmetricPredicate(Predicate):
40
+ """
41
+ Symmetric matrix predicate.
42
+
43
+ Explanation
44
+ ===========
45
+
46
+ ``Q.symmetric(x)`` is true iff ``x`` is a square matrix and is equal to
47
+ its transpose. Every square diagonal matrix is a symmetric matrix.
48
+
49
+ Examples
50
+ ========
51
+
52
+ >>> from sympy import Q, ask, MatrixSymbol
53
+ >>> X = MatrixSymbol('X', 2, 2)
54
+ >>> Y = MatrixSymbol('Y', 2, 3)
55
+ >>> Z = MatrixSymbol('Z', 2, 2)
56
+ >>> ask(Q.symmetric(X*Z), Q.symmetric(X) & Q.symmetric(Z))
57
+ True
58
+ >>> ask(Q.symmetric(X + Z), Q.symmetric(X) & Q.symmetric(Z))
59
+ True
60
+ >>> ask(Q.symmetric(Y))
61
+ False
62
+
63
+
64
+ References
65
+ ==========
66
+
67
+ .. [1] https://en.wikipedia.org/wiki/Symmetric_matrix
68
+
69
+ """
70
+ # TODO: Add handlers to make these keys work with
71
+ # actual matrices and add more examples in the docstring.
72
+ name = 'symmetric'
73
+ handler = Dispatcher("SymmetricHandler", doc="Handler for Q.symmetric.")
74
+
75
+
76
+ class InvertiblePredicate(Predicate):
77
+ """
78
+ Invertible matrix predicate.
79
+
80
+ Explanation
81
+ ===========
82
+
83
+ ``Q.invertible(x)`` is true iff ``x`` is an invertible matrix.
84
+ A square matrix is called invertible only if its determinant is 0.
85
+
86
+ Examples
87
+ ========
88
+
89
+ >>> from sympy import Q, ask, MatrixSymbol
90
+ >>> X = MatrixSymbol('X', 2, 2)
91
+ >>> Y = MatrixSymbol('Y', 2, 3)
92
+ >>> Z = MatrixSymbol('Z', 2, 2)
93
+ >>> ask(Q.invertible(X*Y), Q.invertible(X))
94
+ False
95
+ >>> ask(Q.invertible(X*Z), Q.invertible(X) & Q.invertible(Z))
96
+ True
97
+ >>> ask(Q.invertible(X), Q.fullrank(X) & Q.square(X))
98
+ True
99
+
100
+ References
101
+ ==========
102
+
103
+ .. [1] https://en.wikipedia.org/wiki/Invertible_matrix
104
+
105
+ """
106
+ name = 'invertible'
107
+ handler = Dispatcher("InvertibleHandler", doc="Handler for Q.invertible.")
108
+
109
+
110
+ class OrthogonalPredicate(Predicate):
111
+ """
112
+ Orthogonal matrix predicate.
113
+
114
+ Explanation
115
+ ===========
116
+
117
+ ``Q.orthogonal(x)`` is true iff ``x`` is an orthogonal matrix.
118
+ A square matrix ``M`` is an orthogonal matrix if it satisfies
119
+ ``M^TM = MM^T = I`` where ``M^T`` is the transpose matrix of
120
+ ``M`` and ``I`` is an identity matrix. Note that an orthogonal
121
+ matrix is necessarily invertible.
122
+
123
+ Examples
124
+ ========
125
+
126
+ >>> from sympy import Q, ask, MatrixSymbol, Identity
127
+ >>> X = MatrixSymbol('X', 2, 2)
128
+ >>> Y = MatrixSymbol('Y', 2, 3)
129
+ >>> Z = MatrixSymbol('Z', 2, 2)
130
+ >>> ask(Q.orthogonal(Y))
131
+ False
132
+ >>> ask(Q.orthogonal(X*Z*X), Q.orthogonal(X) & Q.orthogonal(Z))
133
+ True
134
+ >>> ask(Q.orthogonal(Identity(3)))
135
+ True
136
+ >>> ask(Q.invertible(X), Q.orthogonal(X))
137
+ True
138
+
139
+ References
140
+ ==========
141
+
142
+ .. [1] https://en.wikipedia.org/wiki/Orthogonal_matrix
143
+
144
+ """
145
+ name = 'orthogonal'
146
+ handler = Dispatcher("OrthogonalHandler", doc="Handler for key 'orthogonal'.")
147
+
148
+
149
+ class UnitaryPredicate(Predicate):
150
+ """
151
+ Unitary matrix predicate.
152
+
153
+ Explanation
154
+ ===========
155
+
156
+ ``Q.unitary(x)`` is true iff ``x`` is a unitary matrix.
157
+ Unitary matrix is an analogue to orthogonal matrix. A square
158
+ matrix ``M`` with complex elements is unitary if :math:``M^TM = MM^T= I``
159
+ where :math:``M^T`` is the conjugate transpose matrix of ``M``.
160
+
161
+ Examples
162
+ ========
163
+
164
+ >>> from sympy import Q, ask, MatrixSymbol, Identity
165
+ >>> X = MatrixSymbol('X', 2, 2)
166
+ >>> Y = MatrixSymbol('Y', 2, 3)
167
+ >>> Z = MatrixSymbol('Z', 2, 2)
168
+ >>> ask(Q.unitary(Y))
169
+ False
170
+ >>> ask(Q.unitary(X*Z*X), Q.unitary(X) & Q.unitary(Z))
171
+ True
172
+ >>> ask(Q.unitary(Identity(3)))
173
+ True
174
+
175
+ References
176
+ ==========
177
+
178
+ .. [1] https://en.wikipedia.org/wiki/Unitary_matrix
179
+
180
+ """
181
+ name = 'unitary'
182
+ handler = Dispatcher("UnitaryHandler", doc="Handler for key 'unitary'.")
183
+
184
+
185
+ class FullRankPredicate(Predicate):
186
+ """
187
+ Fullrank matrix predicate.
188
+
189
+ Explanation
190
+ ===========
191
+
192
+ ``Q.fullrank(x)`` is true iff ``x`` is a full rank matrix.
193
+ A matrix is full rank if all rows and columns of the matrix
194
+ are linearly independent. A square matrix is full rank iff
195
+ its determinant is nonzero.
196
+
197
+ Examples
198
+ ========
199
+
200
+ >>> from sympy import Q, ask, MatrixSymbol, ZeroMatrix, Identity
201
+ >>> X = MatrixSymbol('X', 2, 2)
202
+ >>> ask(Q.fullrank(X.T), Q.fullrank(X))
203
+ True
204
+ >>> ask(Q.fullrank(ZeroMatrix(3, 3)))
205
+ False
206
+ >>> ask(Q.fullrank(Identity(3)))
207
+ True
208
+
209
+ """
210
+ name = 'fullrank'
211
+ handler = Dispatcher("FullRankHandler", doc="Handler for key 'fullrank'.")
212
+
213
+
214
+ class PositiveDefinitePredicate(Predicate):
215
+ r"""
216
+ Positive definite matrix predicate.
217
+
218
+ Explanation
219
+ ===========
220
+
221
+ If $M$ is a :math:`n \times n` symmetric real matrix, it is said
222
+ to be positive definite if :math:`Z^TMZ` is positive for
223
+ every non-zero column vector $Z$ of $n$ real numbers.
224
+
225
+ Examples
226
+ ========
227
+
228
+ >>> from sympy import Q, ask, MatrixSymbol, Identity
229
+ >>> X = MatrixSymbol('X', 2, 2)
230
+ >>> Y = MatrixSymbol('Y', 2, 3)
231
+ >>> Z = MatrixSymbol('Z', 2, 2)
232
+ >>> ask(Q.positive_definite(Y))
233
+ False
234
+ >>> ask(Q.positive_definite(Identity(3)))
235
+ True
236
+ >>> ask(Q.positive_definite(X + Z), Q.positive_definite(X) &
237
+ ... Q.positive_definite(Z))
238
+ True
239
+
240
+ References
241
+ ==========
242
+
243
+ .. [1] https://en.wikipedia.org/wiki/Positive-definite_matrix
244
+
245
+ """
246
+ name = "positive_definite"
247
+ handler = Dispatcher("PositiveDefiniteHandler", doc="Handler for key 'positive_definite'.")
248
+
249
+
250
+ class UpperTriangularPredicate(Predicate):
251
+ """
252
+ Upper triangular matrix predicate.
253
+
254
+ Explanation
255
+ ===========
256
+
257
+ A matrix $M$ is called upper triangular matrix if :math:`M_{ij}=0`
258
+ for :math:`i<j`.
259
+
260
+ Examples
261
+ ========
262
+
263
+ >>> from sympy import Q, ask, ZeroMatrix, Identity
264
+ >>> ask(Q.upper_triangular(Identity(3)))
265
+ True
266
+ >>> ask(Q.upper_triangular(ZeroMatrix(3, 3)))
267
+ True
268
+
269
+ References
270
+ ==========
271
+
272
+ .. [1] https://mathworld.wolfram.com/UpperTriangularMatrix.html
273
+
274
+ """
275
+ name = "upper_triangular"
276
+ handler = Dispatcher("UpperTriangularHandler", doc="Handler for key 'upper_triangular'.")
277
+
278
+
279
+ class LowerTriangularPredicate(Predicate):
280
+ """
281
+ Lower triangular matrix predicate.
282
+
283
+ Explanation
284
+ ===========
285
+
286
+ A matrix $M$ is called lower triangular matrix if :math:`M_{ij}=0`
287
+ for :math:`i>j`.
288
+
289
+ Examples
290
+ ========
291
+
292
+ >>> from sympy import Q, ask, ZeroMatrix, Identity
293
+ >>> ask(Q.lower_triangular(Identity(3)))
294
+ True
295
+ >>> ask(Q.lower_triangular(ZeroMatrix(3, 3)))
296
+ True
297
+
298
+ References
299
+ ==========
300
+
301
+ .. [1] https://mathworld.wolfram.com/LowerTriangularMatrix.html
302
+
303
+ """
304
+ name = "lower_triangular"
305
+ handler = Dispatcher("LowerTriangularHandler", doc="Handler for key 'lower_triangular'.")
306
+
307
+
308
+ class DiagonalPredicate(Predicate):
309
+ """
310
+ Diagonal matrix predicate.
311
+
312
+ Explanation
313
+ ===========
314
+
315
+ ``Q.diagonal(x)`` is true iff ``x`` is a diagonal matrix. A diagonal
316
+ matrix is a matrix in which the entries outside the main diagonal
317
+ are all zero.
318
+
319
+ Examples
320
+ ========
321
+
322
+ >>> from sympy import Q, ask, MatrixSymbol, ZeroMatrix
323
+ >>> X = MatrixSymbol('X', 2, 2)
324
+ >>> ask(Q.diagonal(ZeroMatrix(3, 3)))
325
+ True
326
+ >>> ask(Q.diagonal(X), Q.lower_triangular(X) &
327
+ ... Q.upper_triangular(X))
328
+ True
329
+
330
+ References
331
+ ==========
332
+
333
+ .. [1] https://en.wikipedia.org/wiki/Diagonal_matrix
334
+
335
+ """
336
+ name = "diagonal"
337
+ handler = Dispatcher("DiagonalHandler", doc="Handler for key 'diagonal'.")
338
+
339
+
340
+ class IntegerElementsPredicate(Predicate):
341
+ """
342
+ Integer elements matrix predicate.
343
+
344
+ Explanation
345
+ ===========
346
+
347
+ ``Q.integer_elements(x)`` is true iff all the elements of ``x``
348
+ are integers.
349
+
350
+ Examples
351
+ ========
352
+
353
+ >>> from sympy import Q, ask, MatrixSymbol
354
+ >>> X = MatrixSymbol('X', 4, 4)
355
+ >>> ask(Q.integer(X[1, 2]), Q.integer_elements(X))
356
+ True
357
+
358
+ """
359
+ name = "integer_elements"
360
+ handler = Dispatcher("IntegerElementsHandler", doc="Handler for key 'integer_elements'.")
361
+
362
+
363
+ class RealElementsPredicate(Predicate):
364
+ """
365
+ Real elements matrix predicate.
366
+
367
+ Explanation
368
+ ===========
369
+
370
+ ``Q.real_elements(x)`` is true iff all the elements of ``x``
371
+ are real numbers.
372
+
373
+ Examples
374
+ ========
375
+
376
+ >>> from sympy import Q, ask, MatrixSymbol
377
+ >>> X = MatrixSymbol('X', 4, 4)
378
+ >>> ask(Q.real(X[1, 2]), Q.real_elements(X))
379
+ True
380
+
381
+ """
382
+ name = "real_elements"
383
+ handler = Dispatcher("RealElementsHandler", doc="Handler for key 'real_elements'.")
384
+
385
+
386
+ class ComplexElementsPredicate(Predicate):
387
+ """
388
+ Complex elements matrix predicate.
389
+
390
+ Explanation
391
+ ===========
392
+
393
+ ``Q.complex_elements(x)`` is true iff all the elements of ``x``
394
+ are complex numbers.
395
+
396
+ Examples
397
+ ========
398
+
399
+ >>> from sympy import Q, ask, MatrixSymbol
400
+ >>> X = MatrixSymbol('X', 4, 4)
401
+ >>> ask(Q.complex(X[1, 2]), Q.complex_elements(X))
402
+ True
403
+ >>> ask(Q.complex_elements(X), Q.integer_elements(X))
404
+ True
405
+
406
+ """
407
+ name = "complex_elements"
408
+ handler = Dispatcher("ComplexElementsHandler", doc="Handler for key 'complex_elements'.")
409
+
410
+
411
+ class SingularPredicate(Predicate):
412
+ """
413
+ Singular matrix predicate.
414
+
415
+ A matrix is singular iff the value of its determinant is 0.
416
+
417
+ Examples
418
+ ========
419
+
420
+ >>> from sympy import Q, ask, MatrixSymbol
421
+ >>> X = MatrixSymbol('X', 4, 4)
422
+ >>> ask(Q.singular(X), Q.invertible(X))
423
+ False
424
+ >>> ask(Q.singular(X), ~Q.invertible(X))
425
+ True
426
+
427
+ References
428
+ ==========
429
+
430
+ .. [1] https://mathworld.wolfram.com/SingularMatrix.html
431
+
432
+ """
433
+ name = "singular"
434
+ handler = Dispatcher("SingularHandler", doc="Predicate fore key 'singular'.")
435
+
436
+
437
+ class NormalPredicate(Predicate):
438
+ """
439
+ Normal matrix predicate.
440
+
441
+ A matrix is normal if it commutes with its conjugate transpose.
442
+
443
+ Examples
444
+ ========
445
+
446
+ >>> from sympy import Q, ask, MatrixSymbol
447
+ >>> X = MatrixSymbol('X', 4, 4)
448
+ >>> ask(Q.normal(X), Q.unitary(X))
449
+ True
450
+
451
+ References
452
+ ==========
453
+
454
+ .. [1] https://en.wikipedia.org/wiki/Normal_matrix
455
+
456
+ """
457
+ name = "normal"
458
+ handler = Dispatcher("NormalHandler", doc="Predicate fore key 'normal'.")
459
+
460
+
461
+ class TriangularPredicate(Predicate):
462
+ """
463
+ Triangular matrix predicate.
464
+
465
+ Explanation
466
+ ===========
467
+
468
+ ``Q.triangular(X)`` is true if ``X`` is one that is either lower
469
+ triangular or upper triangular.
470
+
471
+ Examples
472
+ ========
473
+
474
+ >>> from sympy import Q, ask, MatrixSymbol
475
+ >>> X = MatrixSymbol('X', 4, 4)
476
+ >>> ask(Q.triangular(X), Q.upper_triangular(X))
477
+ True
478
+ >>> ask(Q.triangular(X), Q.lower_triangular(X))
479
+ True
480
+
481
+ References
482
+ ==========
483
+
484
+ .. [1] https://en.wikipedia.org/wiki/Triangular_matrix
485
+
486
+ """
487
+ name = "triangular"
488
+ handler = Dispatcher("TriangularHandler", doc="Predicate fore key 'triangular'.")
489
+
490
+
491
+ class UnitTriangularPredicate(Predicate):
492
+ """
493
+ Unit triangular matrix predicate.
494
+
495
+ Explanation
496
+ ===========
497
+
498
+ A unit triangular matrix is a triangular matrix with 1s
499
+ on the diagonal.
500
+
501
+ Examples
502
+ ========
503
+
504
+ >>> from sympy import Q, ask, MatrixSymbol
505
+ >>> X = MatrixSymbol('X', 4, 4)
506
+ >>> ask(Q.triangular(X), Q.unit_triangular(X))
507
+ True
508
+
509
+ """
510
+ name = "unit_triangular"
511
+ handler = Dispatcher("UnitTriangularHandler", doc="Predicate fore key 'unit_triangular'.")
lib/python3.12/site-packages/sympy/assumptions/predicates/ntheory.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.assumptions import Predicate
2
+ from sympy.multipledispatch import Dispatcher
3
+
4
+
5
+ class PrimePredicate(Predicate):
6
+ """
7
+ Prime number predicate.
8
+
9
+ Explanation
10
+ ===========
11
+
12
+ ``ask(Q.prime(x))`` is true iff ``x`` is a natural number greater
13
+ than 1 that has no positive divisors other than ``1`` and the
14
+ number itself.
15
+
16
+ Examples
17
+ ========
18
+
19
+ >>> from sympy import Q, ask
20
+ >>> ask(Q.prime(0))
21
+ False
22
+ >>> ask(Q.prime(1))
23
+ False
24
+ >>> ask(Q.prime(2))
25
+ True
26
+ >>> ask(Q.prime(20))
27
+ False
28
+ >>> ask(Q.prime(-3))
29
+ False
30
+
31
+ """
32
+ name = 'prime'
33
+ handler = Dispatcher(
34
+ "PrimeHandler",
35
+ doc=("Handler for key 'prime'. Test that an expression represents a prime"
36
+ " number. When the expression is an exact number, the result (when True)"
37
+ " is subject to the limitations of isprime() which is used to return the "
38
+ "result.")
39
+ )
40
+
41
+
42
+ class CompositePredicate(Predicate):
43
+ """
44
+ Composite number predicate.
45
+
46
+ Explanation
47
+ ===========
48
+
49
+ ``ask(Q.composite(x))`` is true iff ``x`` is a positive integer and has
50
+ at least one positive divisor other than ``1`` and the number itself.
51
+
52
+ Examples
53
+ ========
54
+
55
+ >>> from sympy import Q, ask
56
+ >>> ask(Q.composite(0))
57
+ False
58
+ >>> ask(Q.composite(1))
59
+ False
60
+ >>> ask(Q.composite(2))
61
+ False
62
+ >>> ask(Q.composite(20))
63
+ True
64
+
65
+ """
66
+ name = 'composite'
67
+ handler = Dispatcher("CompositeHandler", doc="Handler for key 'composite'.")
68
+
69
+
70
+ class EvenPredicate(Predicate):
71
+ """
72
+ Even number predicate.
73
+
74
+ Explanation
75
+ ===========
76
+
77
+ ``ask(Q.even(x))`` is true iff ``x`` belongs to the set of even
78
+ integers.
79
+
80
+ Examples
81
+ ========
82
+
83
+ >>> from sympy import Q, ask, pi
84
+ >>> ask(Q.even(0))
85
+ True
86
+ >>> ask(Q.even(2))
87
+ True
88
+ >>> ask(Q.even(3))
89
+ False
90
+ >>> ask(Q.even(pi))
91
+ False
92
+
93
+ """
94
+ name = 'even'
95
+ handler = Dispatcher("EvenHandler", doc="Handler for key 'even'.")
96
+
97
+
98
+ class OddPredicate(Predicate):
99
+ """
100
+ Odd number predicate.
101
+
102
+ Explanation
103
+ ===========
104
+
105
+ ``ask(Q.odd(x))`` is true iff ``x`` belongs to the set of odd numbers.
106
+
107
+ Examples
108
+ ========
109
+
110
+ >>> from sympy import Q, ask, pi
111
+ >>> ask(Q.odd(0))
112
+ False
113
+ >>> ask(Q.odd(2))
114
+ False
115
+ >>> ask(Q.odd(3))
116
+ True
117
+ >>> ask(Q.odd(pi))
118
+ False
119
+
120
+ """
121
+ name = 'odd'
122
+ handler = Dispatcher(
123
+ "OddHandler",
124
+ doc=("Handler for key 'odd'. Test that an expression represents an odd"
125
+ " number.")
126
+ )
lib/python3.12/site-packages/sympy/assumptions/predicates/order.py ADDED
@@ -0,0 +1,390 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.assumptions import Predicate
2
+ from sympy.multipledispatch import Dispatcher
3
+
4
+
5
+ class NegativePredicate(Predicate):
6
+ r"""
7
+ Negative number predicate.
8
+
9
+ Explanation
10
+ ===========
11
+
12
+ ``Q.negative(x)`` is true iff ``x`` is a real number and :math:`x < 0`, that is,
13
+ it is in the interval :math:`(-\infty, 0)`. Note in particular that negative
14
+ infinity is not negative.
15
+
16
+ A few important facts about negative numbers:
17
+
18
+ - Note that ``Q.nonnegative`` and ``~Q.negative`` are *not* the same
19
+ thing. ``~Q.negative(x)`` simply means that ``x`` is not negative,
20
+ whereas ``Q.nonnegative(x)`` means that ``x`` is real and not
21
+ negative, i.e., ``Q.nonnegative(x)`` is logically equivalent to
22
+ ``Q.zero(x) | Q.positive(x)``. So for example, ``~Q.negative(I)`` is
23
+ true, whereas ``Q.nonnegative(I)`` is false.
24
+
25
+ - See the documentation of ``Q.real`` for more information about
26
+ related facts.
27
+
28
+ Examples
29
+ ========
30
+
31
+ >>> from sympy import Q, ask, symbols, I
32
+ >>> x = symbols('x')
33
+ >>> ask(Q.negative(x), Q.real(x) & ~Q.positive(x) & ~Q.zero(x))
34
+ True
35
+ >>> ask(Q.negative(-1))
36
+ True
37
+ >>> ask(Q.nonnegative(I))
38
+ False
39
+ >>> ask(~Q.negative(I))
40
+ True
41
+
42
+ """
43
+ name = 'negative'
44
+ handler = Dispatcher(
45
+ "NegativeHandler",
46
+ doc=("Handler for Q.negative. Test that an expression is strictly less"
47
+ " than zero.")
48
+ )
49
+
50
+
51
+ class NonNegativePredicate(Predicate):
52
+ """
53
+ Nonnegative real number predicate.
54
+
55
+ Explanation
56
+ ===========
57
+
58
+ ``ask(Q.nonnegative(x))`` is true iff ``x`` belongs to the set of
59
+ positive numbers including zero.
60
+
61
+ - Note that ``Q.nonnegative`` and ``~Q.negative`` are *not* the same
62
+ thing. ``~Q.negative(x)`` simply means that ``x`` is not negative,
63
+ whereas ``Q.nonnegative(x)`` means that ``x`` is real and not
64
+ negative, i.e., ``Q.nonnegative(x)`` is logically equivalent to
65
+ ``Q.zero(x) | Q.positive(x)``. So for example, ``~Q.negative(I)`` is
66
+ true, whereas ``Q.nonnegative(I)`` is false.
67
+
68
+ Examples
69
+ ========
70
+
71
+ >>> from sympy import Q, ask, I
72
+ >>> ask(Q.nonnegative(1))
73
+ True
74
+ >>> ask(Q.nonnegative(0))
75
+ True
76
+ >>> ask(Q.nonnegative(-1))
77
+ False
78
+ >>> ask(Q.nonnegative(I))
79
+ False
80
+ >>> ask(Q.nonnegative(-I))
81
+ False
82
+
83
+ """
84
+ name = 'nonnegative'
85
+ handler = Dispatcher(
86
+ "NonNegativeHandler",
87
+ doc=("Handler for Q.nonnegative.")
88
+ )
89
+
90
+
91
+ class NonZeroPredicate(Predicate):
92
+ """
93
+ Nonzero real number predicate.
94
+
95
+ Explanation
96
+ ===========
97
+
98
+ ``ask(Q.nonzero(x))`` is true iff ``x`` is real and ``x`` is not zero. Note in
99
+ particular that ``Q.nonzero(x)`` is false if ``x`` is not real. Use
100
+ ``~Q.zero(x)`` if you want the negation of being zero without any real
101
+ assumptions.
102
+
103
+ A few important facts about nonzero numbers:
104
+
105
+ - ``Q.nonzero`` is logically equivalent to ``Q.positive | Q.negative``.
106
+
107
+ - See the documentation of ``Q.real`` for more information about
108
+ related facts.
109
+
110
+ Examples
111
+ ========
112
+
113
+ >>> from sympy import Q, ask, symbols, I, oo
114
+ >>> x = symbols('x')
115
+ >>> print(ask(Q.nonzero(x), ~Q.zero(x)))
116
+ None
117
+ >>> ask(Q.nonzero(x), Q.positive(x))
118
+ True
119
+ >>> ask(Q.nonzero(x), Q.zero(x))
120
+ False
121
+ >>> ask(Q.nonzero(0))
122
+ False
123
+ >>> ask(Q.nonzero(I))
124
+ False
125
+ >>> ask(~Q.zero(I))
126
+ True
127
+ >>> ask(Q.nonzero(oo))
128
+ False
129
+
130
+ """
131
+ name = 'nonzero'
132
+ handler = Dispatcher(
133
+ "NonZeroHandler",
134
+ doc=("Handler for key 'nonzero'. Test that an expression is not identically"
135
+ " zero.")
136
+ )
137
+
138
+
139
+ class ZeroPredicate(Predicate):
140
+ """
141
+ Zero number predicate.
142
+
143
+ Explanation
144
+ ===========
145
+
146
+ ``ask(Q.zero(x))`` is true iff the value of ``x`` is zero.
147
+
148
+ Examples
149
+ ========
150
+
151
+ >>> from sympy import ask, Q, oo, symbols
152
+ >>> x, y = symbols('x, y')
153
+ >>> ask(Q.zero(0))
154
+ True
155
+ >>> ask(Q.zero(1/oo))
156
+ True
157
+ >>> print(ask(Q.zero(0*oo)))
158
+ None
159
+ >>> ask(Q.zero(1))
160
+ False
161
+ >>> ask(Q.zero(x*y), Q.zero(x) | Q.zero(y))
162
+ True
163
+
164
+ """
165
+ name = 'zero'
166
+ handler = Dispatcher(
167
+ "ZeroHandler",
168
+ doc="Handler for key 'zero'."
169
+ )
170
+
171
+
172
+ class NonPositivePredicate(Predicate):
173
+ """
174
+ Nonpositive real number predicate.
175
+
176
+ Explanation
177
+ ===========
178
+
179
+ ``ask(Q.nonpositive(x))`` is true iff ``x`` belongs to the set of
180
+ negative numbers including zero.
181
+
182
+ - Note that ``Q.nonpositive`` and ``~Q.positive`` are *not* the same
183
+ thing. ``~Q.positive(x)`` simply means that ``x`` is not positive,
184
+ whereas ``Q.nonpositive(x)`` means that ``x`` is real and not
185
+ positive, i.e., ``Q.nonpositive(x)`` is logically equivalent to
186
+ `Q.negative(x) | Q.zero(x)``. So for example, ``~Q.positive(I)`` is
187
+ true, whereas ``Q.nonpositive(I)`` is false.
188
+
189
+ Examples
190
+ ========
191
+
192
+ >>> from sympy import Q, ask, I
193
+
194
+ >>> ask(Q.nonpositive(-1))
195
+ True
196
+ >>> ask(Q.nonpositive(0))
197
+ True
198
+ >>> ask(Q.nonpositive(1))
199
+ False
200
+ >>> ask(Q.nonpositive(I))
201
+ False
202
+ >>> ask(Q.nonpositive(-I))
203
+ False
204
+
205
+ """
206
+ name = 'nonpositive'
207
+ handler = Dispatcher(
208
+ "NonPositiveHandler",
209
+ doc="Handler for key 'nonpositive'."
210
+ )
211
+
212
+
213
+ class PositivePredicate(Predicate):
214
+ r"""
215
+ Positive real number predicate.
216
+
217
+ Explanation
218
+ ===========
219
+
220
+ ``Q.positive(x)`` is true iff ``x`` is real and `x > 0`, that is if ``x``
221
+ is in the interval `(0, \infty)`. In particular, infinity is not
222
+ positive.
223
+
224
+ A few important facts about positive numbers:
225
+
226
+ - Note that ``Q.nonpositive`` and ``~Q.positive`` are *not* the same
227
+ thing. ``~Q.positive(x)`` simply means that ``x`` is not positive,
228
+ whereas ``Q.nonpositive(x)`` means that ``x`` is real and not
229
+ positive, i.e., ``Q.nonpositive(x)`` is logically equivalent to
230
+ `Q.negative(x) | Q.zero(x)``. So for example, ``~Q.positive(I)`` is
231
+ true, whereas ``Q.nonpositive(I)`` is false.
232
+
233
+ - See the documentation of ``Q.real`` for more information about
234
+ related facts.
235
+
236
+ Examples
237
+ ========
238
+
239
+ >>> from sympy import Q, ask, symbols, I
240
+ >>> x = symbols('x')
241
+ >>> ask(Q.positive(x), Q.real(x) & ~Q.negative(x) & ~Q.zero(x))
242
+ True
243
+ >>> ask(Q.positive(1))
244
+ True
245
+ >>> ask(Q.nonpositive(I))
246
+ False
247
+ >>> ask(~Q.positive(I))
248
+ True
249
+
250
+ """
251
+ name = 'positive'
252
+ handler = Dispatcher(
253
+ "PositiveHandler",
254
+ doc=("Handler for key 'positive'. Test that an expression is strictly"
255
+ " greater than zero.")
256
+ )
257
+
258
+
259
+ class ExtendedPositivePredicate(Predicate):
260
+ r"""
261
+ Positive extended real number predicate.
262
+
263
+ Explanation
264
+ ===========
265
+
266
+ ``Q.extended_positive(x)`` is true iff ``x`` is extended real and
267
+ `x > 0`, that is if ``x`` is in the interval `(0, \infty]`.
268
+
269
+ Examples
270
+ ========
271
+
272
+ >>> from sympy import ask, I, oo, Q
273
+ >>> ask(Q.extended_positive(1))
274
+ True
275
+ >>> ask(Q.extended_positive(oo))
276
+ True
277
+ >>> ask(Q.extended_positive(I))
278
+ False
279
+
280
+ """
281
+ name = 'extended_positive'
282
+ handler = Dispatcher("ExtendedPositiveHandler")
283
+
284
+
285
+ class ExtendedNegativePredicate(Predicate):
286
+ r"""
287
+ Negative extended real number predicate.
288
+
289
+ Explanation
290
+ ===========
291
+
292
+ ``Q.extended_negative(x)`` is true iff ``x`` is extended real and
293
+ `x < 0`, that is if ``x`` is in the interval `[-\infty, 0)`.
294
+
295
+ Examples
296
+ ========
297
+
298
+ >>> from sympy import ask, I, oo, Q
299
+ >>> ask(Q.extended_negative(-1))
300
+ True
301
+ >>> ask(Q.extended_negative(-oo))
302
+ True
303
+ >>> ask(Q.extended_negative(-I))
304
+ False
305
+
306
+ """
307
+ name = 'extended_negative'
308
+ handler = Dispatcher("ExtendedNegativeHandler")
309
+
310
+
311
+ class ExtendedNonZeroPredicate(Predicate):
312
+ """
313
+ Nonzero extended real number predicate.
314
+
315
+ Explanation
316
+ ===========
317
+
318
+ ``ask(Q.extended_nonzero(x))`` is true iff ``x`` is extended real and
319
+ ``x`` is not zero.
320
+
321
+ Examples
322
+ ========
323
+
324
+ >>> from sympy import ask, I, oo, Q
325
+ >>> ask(Q.extended_nonzero(-1))
326
+ True
327
+ >>> ask(Q.extended_nonzero(oo))
328
+ True
329
+ >>> ask(Q.extended_nonzero(I))
330
+ False
331
+
332
+ """
333
+ name = 'extended_nonzero'
334
+ handler = Dispatcher("ExtendedNonZeroHandler")
335
+
336
+
337
+ class ExtendedNonPositivePredicate(Predicate):
338
+ """
339
+ Nonpositive extended real number predicate.
340
+
341
+ Explanation
342
+ ===========
343
+
344
+ ``ask(Q.extended_nonpositive(x))`` is true iff ``x`` is extended real and
345
+ ``x`` is not positive.
346
+
347
+ Examples
348
+ ========
349
+
350
+ >>> from sympy import ask, I, oo, Q
351
+ >>> ask(Q.extended_nonpositive(-1))
352
+ True
353
+ >>> ask(Q.extended_nonpositive(oo))
354
+ False
355
+ >>> ask(Q.extended_nonpositive(0))
356
+ True
357
+ >>> ask(Q.extended_nonpositive(I))
358
+ False
359
+
360
+ """
361
+ name = 'extended_nonpositive'
362
+ handler = Dispatcher("ExtendedNonPositiveHandler")
363
+
364
+
365
+ class ExtendedNonNegativePredicate(Predicate):
366
+ """
367
+ Nonnegative extended real number predicate.
368
+
369
+ Explanation
370
+ ===========
371
+
372
+ ``ask(Q.extended_nonnegative(x))`` is true iff ``x`` is extended real and
373
+ ``x`` is not negative.
374
+
375
+ Examples
376
+ ========
377
+
378
+ >>> from sympy import ask, I, oo, Q
379
+ >>> ask(Q.extended_nonnegative(-1))
380
+ False
381
+ >>> ask(Q.extended_nonnegative(oo))
382
+ True
383
+ >>> ask(Q.extended_nonnegative(0))
384
+ True
385
+ >>> ask(Q.extended_nonnegative(I))
386
+ False
387
+
388
+ """
389
+ name = 'extended_nonnegative'
390
+ handler = Dispatcher("ExtendedNonNegativeHandler")
lib/python3.12/site-packages/sympy/assumptions/predicates/sets.py ADDED
@@ -0,0 +1,399 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.assumptions import Predicate
2
+ from sympy.multipledispatch import Dispatcher
3
+
4
+
5
+ class IntegerPredicate(Predicate):
6
+ """
7
+ Integer predicate.
8
+
9
+ Explanation
10
+ ===========
11
+
12
+ ``Q.integer(x)`` is true iff ``x`` belongs to the set of integer
13
+ numbers.
14
+
15
+ Examples
16
+ ========
17
+
18
+ >>> from sympy import Q, ask, S
19
+ >>> ask(Q.integer(5))
20
+ True
21
+ >>> ask(Q.integer(S(1)/2))
22
+ False
23
+
24
+ References
25
+ ==========
26
+
27
+ .. [1] https://en.wikipedia.org/wiki/Integer
28
+
29
+ """
30
+ name = 'integer'
31
+ handler = Dispatcher(
32
+ "IntegerHandler",
33
+ doc=("Handler for Q.integer.\n\n"
34
+ "Test that an expression belongs to the field of integer numbers.")
35
+ )
36
+
37
+
38
+ class NonIntegerPredicate(Predicate):
39
+ """
40
+ Non-integer extended real predicate.
41
+ """
42
+ name = 'noninteger'
43
+ handler = Dispatcher(
44
+ "NonIntegerHandler",
45
+ doc=("Handler for Q.noninteger.\n\n"
46
+ "Test that an expression is a non-integer extended real number.")
47
+ )
48
+
49
+
50
+ class RationalPredicate(Predicate):
51
+ """
52
+ Rational number predicate.
53
+
54
+ Explanation
55
+ ===========
56
+
57
+ ``Q.rational(x)`` is true iff ``x`` belongs to the set of
58
+ rational numbers.
59
+
60
+ Examples
61
+ ========
62
+
63
+ >>> from sympy import ask, Q, pi, S
64
+ >>> ask(Q.rational(0))
65
+ True
66
+ >>> ask(Q.rational(S(1)/2))
67
+ True
68
+ >>> ask(Q.rational(pi))
69
+ False
70
+
71
+ References
72
+ ==========
73
+
74
+ .. [1] https://en.wikipedia.org/wiki/Rational_number
75
+
76
+ """
77
+ name = 'rational'
78
+ handler = Dispatcher(
79
+ "RationalHandler",
80
+ doc=("Handler for Q.rational.\n\n"
81
+ "Test that an expression belongs to the field of rational numbers.")
82
+ )
83
+
84
+
85
+ class IrrationalPredicate(Predicate):
86
+ """
87
+ Irrational number predicate.
88
+
89
+ Explanation
90
+ ===========
91
+
92
+ ``Q.irrational(x)`` is true iff ``x`` is any real number that
93
+ cannot be expressed as a ratio of integers.
94
+
95
+ Examples
96
+ ========
97
+
98
+ >>> from sympy import ask, Q, pi, S, I
99
+ >>> ask(Q.irrational(0))
100
+ False
101
+ >>> ask(Q.irrational(S(1)/2))
102
+ False
103
+ >>> ask(Q.irrational(pi))
104
+ True
105
+ >>> ask(Q.irrational(I))
106
+ False
107
+
108
+ References
109
+ ==========
110
+
111
+ .. [1] https://en.wikipedia.org/wiki/Irrational_number
112
+
113
+ """
114
+ name = 'irrational'
115
+ handler = Dispatcher(
116
+ "IrrationalHandler",
117
+ doc=("Handler for Q.irrational.\n\n"
118
+ "Test that an expression is irrational numbers.")
119
+ )
120
+
121
+
122
+ class RealPredicate(Predicate):
123
+ r"""
124
+ Real number predicate.
125
+
126
+ Explanation
127
+ ===========
128
+
129
+ ``Q.real(x)`` is true iff ``x`` is a real number, i.e., it is in the
130
+ interval `(-\infty, \infty)`. Note that, in particular the
131
+ infinities are not real. Use ``Q.extended_real`` if you want to
132
+ consider those as well.
133
+
134
+ A few important facts about reals:
135
+
136
+ - Every real number is positive, negative, or zero. Furthermore,
137
+ because these sets are pairwise disjoint, each real number is
138
+ exactly one of those three.
139
+
140
+ - Every real number is also complex.
141
+
142
+ - Every real number is finite.
143
+
144
+ - Every real number is either rational or irrational.
145
+
146
+ - Every real number is either algebraic or transcendental.
147
+
148
+ - The facts ``Q.negative``, ``Q.zero``, ``Q.positive``,
149
+ ``Q.nonnegative``, ``Q.nonpositive``, ``Q.nonzero``,
150
+ ``Q.integer``, ``Q.rational``, and ``Q.irrational`` all imply
151
+ ``Q.real``, as do all facts that imply those facts.
152
+
153
+ - The facts ``Q.algebraic``, and ``Q.transcendental`` do not imply
154
+ ``Q.real``; they imply ``Q.complex``. An algebraic or
155
+ transcendental number may or may not be real.
156
+
157
+ - The "non" facts (i.e., ``Q.nonnegative``, ``Q.nonzero``,
158
+ ``Q.nonpositive`` and ``Q.noninteger``) are not equivalent to
159
+ not the fact, but rather, not the fact *and* ``Q.real``.
160
+ For example, ``Q.nonnegative`` means ``~Q.negative & Q.real``.
161
+ So for example, ``I`` is not nonnegative, nonzero, or
162
+ nonpositive.
163
+
164
+ Examples
165
+ ========
166
+
167
+ >>> from sympy import Q, ask, symbols
168
+ >>> x = symbols('x')
169
+ >>> ask(Q.real(x), Q.positive(x))
170
+ True
171
+ >>> ask(Q.real(0))
172
+ True
173
+
174
+ References
175
+ ==========
176
+
177
+ .. [1] https://en.wikipedia.org/wiki/Real_number
178
+
179
+ """
180
+ name = 'real'
181
+ handler = Dispatcher(
182
+ "RealHandler",
183
+ doc=("Handler for Q.real.\n\n"
184
+ "Test that an expression belongs to the field of real numbers.")
185
+ )
186
+
187
+
188
+ class ExtendedRealPredicate(Predicate):
189
+ r"""
190
+ Extended real predicate.
191
+
192
+ Explanation
193
+ ===========
194
+
195
+ ``Q.extended_real(x)`` is true iff ``x`` is a real number or
196
+ `\{-\infty, \infty\}`.
197
+
198
+ See documentation of ``Q.real`` for more information about related
199
+ facts.
200
+
201
+ Examples
202
+ ========
203
+
204
+ >>> from sympy import ask, Q, oo, I
205
+ >>> ask(Q.extended_real(1))
206
+ True
207
+ >>> ask(Q.extended_real(I))
208
+ False
209
+ >>> ask(Q.extended_real(oo))
210
+ True
211
+
212
+ """
213
+ name = 'extended_real'
214
+ handler = Dispatcher(
215
+ "ExtendedRealHandler",
216
+ doc=("Handler for Q.extended_real.\n\n"
217
+ "Test that an expression belongs to the field of extended real\n"
218
+ "numbers, that is real numbers union {Infinity, -Infinity}.")
219
+ )
220
+
221
+
222
+ class HermitianPredicate(Predicate):
223
+ """
224
+ Hermitian predicate.
225
+
226
+ Explanation
227
+ ===========
228
+
229
+ ``ask(Q.hermitian(x))`` is true iff ``x`` belongs to the set of
230
+ Hermitian operators.
231
+
232
+ References
233
+ ==========
234
+
235
+ .. [1] https://mathworld.wolfram.com/HermitianOperator.html
236
+
237
+ """
238
+ # TODO: Add examples
239
+ name = 'hermitian'
240
+ handler = Dispatcher(
241
+ "HermitianHandler",
242
+ doc=("Handler for Q.hermitian.\n\n"
243
+ "Test that an expression belongs to the field of Hermitian operators.")
244
+ )
245
+
246
+
247
+ class ComplexPredicate(Predicate):
248
+ """
249
+ Complex number predicate.
250
+
251
+ Explanation
252
+ ===========
253
+
254
+ ``Q.complex(x)`` is true iff ``x`` belongs to the set of complex
255
+ numbers. Note that every complex number is finite.
256
+
257
+ Examples
258
+ ========
259
+
260
+ >>> from sympy import Q, Symbol, ask, I, oo
261
+ >>> x = Symbol('x')
262
+ >>> ask(Q.complex(0))
263
+ True
264
+ >>> ask(Q.complex(2 + 3*I))
265
+ True
266
+ >>> ask(Q.complex(oo))
267
+ False
268
+
269
+ References
270
+ ==========
271
+
272
+ .. [1] https://en.wikipedia.org/wiki/Complex_number
273
+
274
+ """
275
+ name = 'complex'
276
+ handler = Dispatcher(
277
+ "ComplexHandler",
278
+ doc=("Handler for Q.complex.\n\n"
279
+ "Test that an expression belongs to the field of complex numbers.")
280
+ )
281
+
282
+
283
+ class ImaginaryPredicate(Predicate):
284
+ """
285
+ Imaginary number predicate.
286
+
287
+ Explanation
288
+ ===========
289
+
290
+ ``Q.imaginary(x)`` is true iff ``x`` can be written as a real
291
+ number multiplied by the imaginary unit ``I``. Please note that ``0``
292
+ is not considered to be an imaginary number.
293
+
294
+ Examples
295
+ ========
296
+
297
+ >>> from sympy import Q, ask, I
298
+ >>> ask(Q.imaginary(3*I))
299
+ True
300
+ >>> ask(Q.imaginary(2 + 3*I))
301
+ False
302
+ >>> ask(Q.imaginary(0))
303
+ False
304
+
305
+ References
306
+ ==========
307
+
308
+ .. [1] https://en.wikipedia.org/wiki/Imaginary_number
309
+
310
+ """
311
+ name = 'imaginary'
312
+ handler = Dispatcher(
313
+ "ImaginaryHandler",
314
+ doc=("Handler for Q.imaginary.\n\n"
315
+ "Test that an expression belongs to the field of imaginary numbers,\n"
316
+ "that is, numbers in the form x*I, where x is real.")
317
+ )
318
+
319
+
320
+ class AntihermitianPredicate(Predicate):
321
+ """
322
+ Antihermitian predicate.
323
+
324
+ Explanation
325
+ ===========
326
+
327
+ ``Q.antihermitian(x)`` is true iff ``x`` belongs to the field of
328
+ antihermitian operators, i.e., operators in the form ``x*I``, where
329
+ ``x`` is Hermitian.
330
+
331
+ References
332
+ ==========
333
+
334
+ .. [1] https://mathworld.wolfram.com/HermitianOperator.html
335
+
336
+ """
337
+ # TODO: Add examples
338
+ name = 'antihermitian'
339
+ handler = Dispatcher(
340
+ "AntiHermitianHandler",
341
+ doc=("Handler for Q.antihermitian.\n\n"
342
+ "Test that an expression belongs to the field of anti-Hermitian\n"
343
+ "operators, that is, operators in the form x*I, where x is Hermitian.")
344
+ )
345
+
346
+
347
+ class AlgebraicPredicate(Predicate):
348
+ r"""
349
+ Algebraic number predicate.
350
+
351
+ Explanation
352
+ ===========
353
+
354
+ ``Q.algebraic(x)`` is true iff ``x`` belongs to the set of
355
+ algebraic numbers. ``x`` is algebraic if there is some polynomial
356
+ in ``p(x)\in \mathbb\{Q\}[x]`` such that ``p(x) = 0``.
357
+
358
+ Examples
359
+ ========
360
+
361
+ >>> from sympy import ask, Q, sqrt, I, pi
362
+ >>> ask(Q.algebraic(sqrt(2)))
363
+ True
364
+ >>> ask(Q.algebraic(I))
365
+ True
366
+ >>> ask(Q.algebraic(pi))
367
+ False
368
+
369
+ References
370
+ ==========
371
+
372
+ .. [1] https://en.wikipedia.org/wiki/Algebraic_number
373
+
374
+ """
375
+ name = 'algebraic'
376
+ AlgebraicHandler = Dispatcher(
377
+ "AlgebraicHandler",
378
+ doc="""Handler for Q.algebraic key."""
379
+ )
380
+
381
+
382
+ class TranscendentalPredicate(Predicate):
383
+ """
384
+ Transcedental number predicate.
385
+
386
+ Explanation
387
+ ===========
388
+
389
+ ``Q.transcendental(x)`` is true iff ``x`` belongs to the set of
390
+ transcendental numbers. A transcendental number is a real
391
+ or complex number that is not algebraic.
392
+
393
+ """
394
+ # TODO: Add examples
395
+ name = 'transcendental'
396
+ handler = Dispatcher(
397
+ "Transcendental",
398
+ doc="""Handler for Q.transcendental key."""
399
+ )
lib/python3.12/site-packages/sympy/parsing/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (342 Bytes). View file
 
lib/python3.12/site-packages/sympy/parsing/__pycache__/ast_parser.cpython-312.pyc ADDED
Binary file (4.39 kB). View file
 
lib/python3.12/site-packages/sympy/parsing/__pycache__/mathematica.cpython-312.pyc ADDED
Binary file (44.7 kB). View file
 
lib/python3.12/site-packages/sympy/parsing/__pycache__/maxima.cpython-312.pyc ADDED
Binary file (3.9 kB). View file
 
lib/python3.12/site-packages/sympy/parsing/c/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """Used for translating C source code into a SymPy expression"""
lib/python3.12/site-packages/sympy/parsing/c/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (267 Bytes). View file
 
lib/python3.12/site-packages/sympy/parsing/c/__pycache__/c_parser.cpython-312.pyc ADDED
Binary file (42.1 kB). View file
 
lib/python3.12/site-packages/sympy/parsing/c/c_parser.py ADDED
@@ -0,0 +1,1058 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.external import import_module
2
+ import os
3
+
4
+ cin = import_module('clang.cindex', import_kwargs = {'fromlist': ['cindex']})
5
+
6
+ """
7
+ This module contains all the necessary Classes and Function used to Parse C and
8
+ C++ code into SymPy expression
9
+ The module serves as a backend for SymPyExpression to parse C code
10
+ It is also dependent on Clang's AST and SymPy's Codegen AST.
11
+ The module only supports the features currently supported by the Clang and
12
+ codegen AST which will be updated as the development of codegen AST and this
13
+ module progresses.
14
+ You might find unexpected bugs and exceptions while using the module, feel free
15
+ to report them to the SymPy Issue Tracker
16
+
17
+ Features Supported
18
+ ==================
19
+
20
+ - Variable Declarations (integers and reals)
21
+ - Assignment (using integer & floating literal and function calls)
22
+ - Function Definitions and Declaration
23
+ - Function Calls
24
+ - Compound statements, Return statements
25
+
26
+ Notes
27
+ =====
28
+
29
+ The module is dependent on an external dependency which needs to be installed
30
+ to use the features of this module.
31
+
32
+ Clang: The C and C++ compiler which is used to extract an AST from the provided
33
+ C source code.
34
+
35
+ References
36
+ ==========
37
+
38
+ .. [1] https://github.com/sympy/sympy/issues
39
+ .. [2] https://clang.llvm.org/docs/
40
+ .. [3] https://clang.llvm.org/docs/IntroductionToTheClangAST.html
41
+
42
+ """
43
+
44
+ if cin:
45
+ from sympy.codegen.ast import (Variable, Integer, Float,
46
+ FunctionPrototype, FunctionDefinition, FunctionCall,
47
+ none, Return, Assignment, intc, int8, int16, int64,
48
+ uint8, uint16, uint32, uint64, float32, float64, float80,
49
+ aug_assign, bool_, While, CodeBlock)
50
+ from sympy.codegen.cnodes import (PreDecrement, PostDecrement,
51
+ PreIncrement, PostIncrement)
52
+ from sympy.core import Add, Mod, Mul, Pow, Rel
53
+ from sympy.logic.boolalg import And, as_Boolean, Not, Or
54
+ from sympy.core.symbol import Symbol
55
+ from sympy.core.sympify import sympify
56
+ from sympy.logic.boolalg import (false, true)
57
+ import sys
58
+ import tempfile
59
+
60
+ class BaseParser:
61
+ """Base Class for the C parser"""
62
+
63
+ def __init__(self):
64
+ """Initializes the Base parser creating a Clang AST index"""
65
+ self.index = cin.Index.create()
66
+
67
+ def diagnostics(self, out):
68
+ """Diagostics function for the Clang AST"""
69
+ for diag in self.tu.diagnostics:
70
+ # tu = translation unit
71
+ print('%s %s (line %s, col %s) %s' % (
72
+ {
73
+ 4: 'FATAL',
74
+ 3: 'ERROR',
75
+ 2: 'WARNING',
76
+ 1: 'NOTE',
77
+ 0: 'IGNORED',
78
+ }[diag.severity],
79
+ diag.location.file,
80
+ diag.location.line,
81
+ diag.location.column,
82
+ diag.spelling
83
+ ), file=out)
84
+
85
+ class CCodeConverter(BaseParser):
86
+ """The Code Convereter for Clang AST
87
+
88
+ The converter object takes the C source code or file as input and
89
+ converts them to SymPy Expressions.
90
+ """
91
+
92
+ def __init__(self):
93
+ """Initializes the code converter"""
94
+ super().__init__()
95
+ self._py_nodes = []
96
+ self._data_types = {
97
+ "void": {
98
+ cin.TypeKind.VOID: none
99
+ },
100
+ "bool": {
101
+ cin.TypeKind.BOOL: bool_
102
+ },
103
+ "int": {
104
+ cin.TypeKind.SCHAR: int8,
105
+ cin.TypeKind.SHORT: int16,
106
+ cin.TypeKind.INT: intc,
107
+ cin.TypeKind.LONG: int64,
108
+ cin.TypeKind.UCHAR: uint8,
109
+ cin.TypeKind.USHORT: uint16,
110
+ cin.TypeKind.UINT: uint32,
111
+ cin.TypeKind.ULONG: uint64
112
+ },
113
+ "float": {
114
+ cin.TypeKind.FLOAT: float32,
115
+ cin.TypeKind.DOUBLE: float64,
116
+ cin.TypeKind.LONGDOUBLE: float80
117
+ }
118
+ }
119
+
120
+ def parse(self, filename, flags):
121
+ """Function to parse a file with C source code
122
+
123
+ It takes the filename as an attribute and creates a Clang AST
124
+ Translation Unit parsing the file.
125
+ Then the transformation function is called on the translation unit,
126
+ whose reults are collected into a list which is returned by the
127
+ function.
128
+
129
+ Parameters
130
+ ==========
131
+
132
+ filename : string
133
+ Path to the C file to be parsed
134
+
135
+ flags: list
136
+ Arguments to be passed to Clang while parsing the C code
137
+
138
+ Returns
139
+ =======
140
+
141
+ py_nodes: list
142
+ A list of SymPy AST nodes
143
+
144
+ """
145
+ filepath = os.path.abspath(filename)
146
+ self.tu = self.index.parse(
147
+ filepath,
148
+ args=flags,
149
+ options=cin.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD
150
+ )
151
+ for child in self.tu.cursor.get_children():
152
+ if child.kind == cin.CursorKind.VAR_DECL or child.kind == cin.CursorKind.FUNCTION_DECL:
153
+ self._py_nodes.append(self.transform(child))
154
+ return self._py_nodes
155
+
156
+ def parse_str(self, source, flags):
157
+ """Function to parse a string with C source code
158
+
159
+ It takes the source code as an attribute, stores it in a temporary
160
+ file and creates a Clang AST Translation Unit parsing the file.
161
+ Then the transformation function is called on the translation unit,
162
+ whose reults are collected into a list which is returned by the
163
+ function.
164
+
165
+ Parameters
166
+ ==========
167
+
168
+ source : string
169
+ A string containing the C source code to be parsed
170
+
171
+ flags: list
172
+ Arguments to be passed to Clang while parsing the C code
173
+
174
+ Returns
175
+ =======
176
+
177
+ py_nodes: list
178
+ A list of SymPy AST nodes
179
+
180
+ """
181
+ file = tempfile.NamedTemporaryFile(mode = 'w+', suffix = '.cpp')
182
+ file.write(source)
183
+ file.seek(0)
184
+ self.tu = self.index.parse(
185
+ file.name,
186
+ args=flags,
187
+ options=cin.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD
188
+ )
189
+ file.close()
190
+ for child in self.tu.cursor.get_children():
191
+ if child.kind == cin.CursorKind.VAR_DECL or child.kind == cin.CursorKind.FUNCTION_DECL:
192
+ self._py_nodes.append(self.transform(child))
193
+ return self._py_nodes
194
+
195
+ def transform(self, node):
196
+ """Transformation Function for Clang AST nodes
197
+
198
+ It determines the kind of node and calls the respective
199
+ transformation function for that node.
200
+
201
+ Raises
202
+ ======
203
+
204
+ NotImplementedError : if the transformation for the provided node
205
+ is not implemented
206
+
207
+ """
208
+ handler = getattr(self, 'transform_%s' % node.kind.name.lower(), None)
209
+
210
+ if handler is None:
211
+ print(
212
+ "Ignoring node of type %s (%s)" % (
213
+ node.kind,
214
+ ' '.join(
215
+ t.spelling for t in node.get_tokens())
216
+ ),
217
+ file=sys.stderr
218
+ )
219
+
220
+ return handler(node)
221
+
222
+ def transform_var_decl(self, node):
223
+ """Transformation Function for Variable Declaration
224
+
225
+ Used to create nodes for variable declarations and assignments with
226
+ values or function call for the respective nodes in the clang AST
227
+
228
+ Returns
229
+ =======
230
+
231
+ A variable node as Declaration, with the initial value if given
232
+
233
+ Raises
234
+ ======
235
+
236
+ NotImplementedError : if called for data types not currently
237
+ implemented
238
+
239
+ Notes
240
+ =====
241
+
242
+ The function currently supports following data types:
243
+
244
+ Boolean:
245
+ bool, _Bool
246
+
247
+ Integer:
248
+ 8-bit: signed char and unsigned char
249
+ 16-bit: short, short int, signed short,
250
+ signed short int, unsigned short, unsigned short int
251
+ 32-bit: int, signed int, unsigned int
252
+ 64-bit: long, long int, signed long,
253
+ signed long int, unsigned long, unsigned long int
254
+
255
+ Floating point:
256
+ Single Precision: float
257
+ Double Precision: double
258
+ Extended Precision: long double
259
+
260
+ """
261
+ if node.type.kind in self._data_types["int"]:
262
+ type = self._data_types["int"][node.type.kind]
263
+ elif node.type.kind in self._data_types["float"]:
264
+ type = self._data_types["float"][node.type.kind]
265
+ elif node.type.kind in self._data_types["bool"]:
266
+ type = self._data_types["bool"][node.type.kind]
267
+ else:
268
+ raise NotImplementedError("Only bool, int "
269
+ "and float are supported")
270
+ try:
271
+ children = node.get_children()
272
+ child = next(children)
273
+
274
+ #ignoring namespace and type details for the variable
275
+ while child.kind == cin.CursorKind.NAMESPACE_REF or child.kind == cin.CursorKind.TYPE_REF:
276
+ child = next(children)
277
+
278
+ val = self.transform(child)
279
+
280
+ supported_rhs = [
281
+ cin.CursorKind.INTEGER_LITERAL,
282
+ cin.CursorKind.FLOATING_LITERAL,
283
+ cin.CursorKind.UNEXPOSED_EXPR,
284
+ cin.CursorKind.BINARY_OPERATOR,
285
+ cin.CursorKind.PAREN_EXPR,
286
+ cin.CursorKind.UNARY_OPERATOR,
287
+ cin.CursorKind.CXX_BOOL_LITERAL_EXPR
288
+ ]
289
+
290
+ if child.kind in supported_rhs:
291
+ if isinstance(val, str):
292
+ value = Symbol(val)
293
+ elif isinstance(val, bool):
294
+ if node.type.kind in self._data_types["int"]:
295
+ value = Integer(0) if val == False else Integer(1)
296
+ elif node.type.kind in self._data_types["float"]:
297
+ value = Float(0.0) if val == False else Float(1.0)
298
+ elif node.type.kind in self._data_types["bool"]:
299
+ value = sympify(val)
300
+ elif isinstance(val, (Integer, int, Float, float)):
301
+ if node.type.kind in self._data_types["int"]:
302
+ value = Integer(val)
303
+ elif node.type.kind in self._data_types["float"]:
304
+ value = Float(val)
305
+ elif node.type.kind in self._data_types["bool"]:
306
+ value = sympify(bool(val))
307
+ else:
308
+ value = val
309
+
310
+ return Variable(
311
+ node.spelling
312
+ ).as_Declaration(
313
+ type = type,
314
+ value = value
315
+ )
316
+
317
+ elif child.kind == cin.CursorKind.CALL_EXPR:
318
+ return Variable(
319
+ node.spelling
320
+ ).as_Declaration(
321
+ value = val
322
+ )
323
+
324
+ else:
325
+ raise NotImplementedError("Given "
326
+ "variable declaration \"{}\" "
327
+ "is not possible to parse yet!"
328
+ .format(" ".join(
329
+ t.spelling for t in node.get_tokens()
330
+ )
331
+ ))
332
+
333
+ except StopIteration:
334
+ return Variable(
335
+ node.spelling
336
+ ).as_Declaration(
337
+ type = type
338
+ )
339
+
340
+ def transform_function_decl(self, node):
341
+ """Transformation Function For Function Declaration
342
+
343
+ Used to create nodes for function declarations and definitions for
344
+ the respective nodes in the clang AST
345
+
346
+ Returns
347
+ =======
348
+
349
+ function : Codegen AST node
350
+ - FunctionPrototype node if function body is not present
351
+ - FunctionDefinition node if the function body is present
352
+
353
+
354
+ """
355
+
356
+ if node.result_type.kind in self._data_types["int"]:
357
+ ret_type = self._data_types["int"][node.result_type.kind]
358
+ elif node.result_type.kind in self._data_types["float"]:
359
+ ret_type = self._data_types["float"][node.result_type.kind]
360
+ elif node.result_type.kind in self._data_types["bool"]:
361
+ ret_type = self._data_types["bool"][node.result_type.kind]
362
+ elif node.result_type.kind in self._data_types["void"]:
363
+ ret_type = self._data_types["void"][node.result_type.kind]
364
+ else:
365
+ raise NotImplementedError("Only void, bool, int "
366
+ "and float are supported")
367
+ body = []
368
+ param = []
369
+
370
+ # Subsequent nodes will be the parameters for the function.
371
+ for child in node.get_children():
372
+ decl = self.transform(child)
373
+ if child.kind == cin.CursorKind.PARM_DECL:
374
+ param.append(decl)
375
+ elif child.kind == cin.CursorKind.COMPOUND_STMT:
376
+ for val in decl:
377
+ body.append(val)
378
+ else:
379
+ body.append(decl)
380
+
381
+ if body == []:
382
+ function = FunctionPrototype(
383
+ return_type = ret_type,
384
+ name = node.spelling,
385
+ parameters = param
386
+ )
387
+ else:
388
+ function = FunctionDefinition(
389
+ return_type = ret_type,
390
+ name = node.spelling,
391
+ parameters = param,
392
+ body = body
393
+ )
394
+ return function
395
+
396
+ def transform_parm_decl(self, node):
397
+ """Transformation function for Parameter Declaration
398
+
399
+ Used to create parameter nodes for the required functions for the
400
+ respective nodes in the clang AST
401
+
402
+ Returns
403
+ =======
404
+
405
+ param : Codegen AST Node
406
+ Variable node with the value and type of the variable
407
+
408
+ Raises
409
+ ======
410
+
411
+ ValueError if multiple children encountered in the parameter node
412
+
413
+ """
414
+ if node.type.kind in self._data_types["int"]:
415
+ type = self._data_types["int"][node.type.kind]
416
+ elif node.type.kind in self._data_types["float"]:
417
+ type = self._data_types["float"][node.type.kind]
418
+ elif node.type.kind in self._data_types["bool"]:
419
+ type = self._data_types["bool"][node.type.kind]
420
+ else:
421
+ raise NotImplementedError("Only bool, int "
422
+ "and float are supported")
423
+ try:
424
+ children = node.get_children()
425
+ child = next(children)
426
+
427
+ # Any namespace nodes can be ignored
428
+ while child.kind in [cin.CursorKind.NAMESPACE_REF,
429
+ cin.CursorKind.TYPE_REF,
430
+ cin.CursorKind.TEMPLATE_REF]:
431
+ child = next(children)
432
+
433
+ # If there is a child, it is the default value of the parameter.
434
+ lit = self.transform(child)
435
+ if node.type.kind in self._data_types["int"]:
436
+ val = Integer(lit)
437
+ elif node.type.kind in self._data_types["float"]:
438
+ val = Float(lit)
439
+ elif node.type.kind in self._data_types["bool"]:
440
+ val = sympify(bool(lit))
441
+ else:
442
+ raise NotImplementedError("Only bool, int "
443
+ "and float are supported")
444
+
445
+ param = Variable(
446
+ node.spelling
447
+ ).as_Declaration(
448
+ type = type,
449
+ value = val
450
+ )
451
+ except StopIteration:
452
+ param = Variable(
453
+ node.spelling
454
+ ).as_Declaration(
455
+ type = type
456
+ )
457
+
458
+ try:
459
+ self.transform(next(children))
460
+ raise ValueError("Can't handle multiple children on parameter")
461
+ except StopIteration:
462
+ pass
463
+
464
+ return param
465
+
466
+ def transform_integer_literal(self, node):
467
+ """Transformation function for integer literal
468
+
469
+ Used to get the value and type of the given integer literal.
470
+
471
+ Returns
472
+ =======
473
+
474
+ val : list
475
+ List with two arguments type and Value
476
+ type contains the type of the integer
477
+ value contains the value stored in the variable
478
+
479
+ Notes
480
+ =====
481
+
482
+ Only Base Integer type supported for now
483
+
484
+ """
485
+ try:
486
+ value = next(node.get_tokens()).spelling
487
+ except StopIteration:
488
+ # No tokens
489
+ value = node.literal
490
+ return int(value)
491
+
492
+ def transform_floating_literal(self, node):
493
+ """Transformation function for floating literal
494
+
495
+ Used to get the value and type of the given floating literal.
496
+
497
+ Returns
498
+ =======
499
+
500
+ val : list
501
+ List with two arguments type and Value
502
+ type contains the type of float
503
+ value contains the value stored in the variable
504
+
505
+ Notes
506
+ =====
507
+
508
+ Only Base Float type supported for now
509
+
510
+ """
511
+ try:
512
+ value = next(node.get_tokens()).spelling
513
+ except (StopIteration, ValueError):
514
+ # No tokens
515
+ value = node.literal
516
+ return float(value)
517
+
518
+ def transform_string_literal(self, node):
519
+ #TODO: No string type in AST
520
+ #type =
521
+ #try:
522
+ # value = next(node.get_tokens()).spelling
523
+ #except (StopIteration, ValueError):
524
+ # No tokens
525
+ # value = node.literal
526
+ #val = [type, value]
527
+ #return val
528
+ pass
529
+
530
+ def transform_character_literal(self, node):
531
+ """Transformation function for character literal
532
+
533
+ Used to get the value of the given character literal.
534
+
535
+ Returns
536
+ =======
537
+
538
+ val : int
539
+ val contains the ascii value of the character literal
540
+
541
+ Notes
542
+ =====
543
+
544
+ Only for cases where character is assigned to a integer value,
545
+ since character literal is not in SymPy AST
546
+
547
+ """
548
+ try:
549
+ value = next(node.get_tokens()).spelling
550
+ except (StopIteration, ValueError):
551
+ # No tokens
552
+ value = node.literal
553
+ return ord(str(value[1]))
554
+
555
+ def transform_cxx_bool_literal_expr(self, node):
556
+ """Transformation function for boolean literal
557
+
558
+ Used to get the value of the given boolean literal.
559
+
560
+ Returns
561
+ =======
562
+
563
+ value : bool
564
+ value contains the boolean value of the variable
565
+
566
+ """
567
+ try:
568
+ value = next(node.get_tokens()).spelling
569
+ except (StopIteration, ValueError):
570
+ value = node.literal
571
+ return True if value == 'true' else False
572
+
573
+ def transform_unexposed_decl(self,node):
574
+ """Transformation function for unexposed declarations"""
575
+ pass
576
+
577
+ def transform_unexposed_expr(self, node):
578
+ """Transformation function for unexposed expression
579
+
580
+ Unexposed expressions are used to wrap float, double literals and
581
+ expressions
582
+
583
+ Returns
584
+ =======
585
+
586
+ expr : Codegen AST Node
587
+ the result from the wrapped expression
588
+
589
+ None : NoneType
590
+ No childs are found for the node
591
+
592
+ Raises
593
+ ======
594
+
595
+ ValueError if the expression contains multiple children
596
+
597
+ """
598
+ # Ignore unexposed nodes; pass whatever is the first
599
+ # (and should be only) child unaltered.
600
+ try:
601
+ children = node.get_children()
602
+ expr = self.transform(next(children))
603
+ except StopIteration:
604
+ return None
605
+
606
+ try:
607
+ next(children)
608
+ raise ValueError("Unexposed expression has > 1 children.")
609
+ except StopIteration:
610
+ pass
611
+
612
+ return expr
613
+
614
+ def transform_decl_ref_expr(self, node):
615
+ """Returns the name of the declaration reference"""
616
+ return node.spelling
617
+
618
+ def transform_call_expr(self, node):
619
+ """Transformation function for a call expression
620
+
621
+ Used to create function call nodes for the function calls present
622
+ in the C code
623
+
624
+ Returns
625
+ =======
626
+
627
+ FunctionCall : Codegen AST Node
628
+ FunctionCall node with parameters if any parameters are present
629
+
630
+ """
631
+ param = []
632
+ children = node.get_children()
633
+ child = next(children)
634
+
635
+ while child.kind == cin.CursorKind.NAMESPACE_REF:
636
+ child = next(children)
637
+ while child.kind == cin.CursorKind.TYPE_REF:
638
+ child = next(children)
639
+
640
+ first_child = self.transform(child)
641
+ try:
642
+ for child in children:
643
+ arg = self.transform(child)
644
+ if child.kind == cin.CursorKind.INTEGER_LITERAL:
645
+ param.append(Integer(arg))
646
+ elif child.kind == cin.CursorKind.FLOATING_LITERAL:
647
+ param.append(Float(arg))
648
+ else:
649
+ param.append(arg)
650
+ return FunctionCall(first_child, param)
651
+
652
+ except StopIteration:
653
+ return FunctionCall(first_child)
654
+
655
+ def transform_return_stmt(self, node):
656
+ """Returns the Return Node for a return statement"""
657
+ return Return(next(node.get_children()).spelling)
658
+
659
+ def transform_compound_stmt(self, node):
660
+ """Transformation function for compond statemets
661
+
662
+ Returns
663
+ =======
664
+
665
+ expr : list
666
+ list of Nodes for the expressions present in the statement
667
+
668
+ None : NoneType
669
+ if the compound statement is empty
670
+
671
+ """
672
+ expr = []
673
+ children = node.get_children()
674
+
675
+ for child in children:
676
+ expr.append(self.transform(child))
677
+ return expr
678
+
679
+ def transform_decl_stmt(self, node):
680
+ """Transformation function for declaration statements
681
+
682
+ These statements are used to wrap different kinds of declararions
683
+ like variable or function declaration
684
+ The function calls the transformer function for the child of the
685
+ given node
686
+
687
+ Returns
688
+ =======
689
+
690
+ statement : Codegen AST Node
691
+ contains the node returned by the children node for the type of
692
+ declaration
693
+
694
+ Raises
695
+ ======
696
+
697
+ ValueError if multiple children present
698
+
699
+ """
700
+ try:
701
+ children = node.get_children()
702
+ statement = self.transform(next(children))
703
+ except StopIteration:
704
+ pass
705
+
706
+ try:
707
+ self.transform(next(children))
708
+ raise ValueError("Don't know how to handle multiple statements")
709
+ except StopIteration:
710
+ pass
711
+
712
+ return statement
713
+
714
+ def transform_paren_expr(self, node):
715
+ """Transformation function for Parenthesized expressions
716
+
717
+ Returns the result from its children nodes
718
+
719
+ """
720
+ return self.transform(next(node.get_children()))
721
+
722
+ def transform_compound_assignment_operator(self, node):
723
+ """Transformation function for handling shorthand operators
724
+
725
+ Returns
726
+ =======
727
+
728
+ augmented_assignment_expression: Codegen AST node
729
+ shorthand assignment expression represented as Codegen AST
730
+
731
+ Raises
732
+ ======
733
+
734
+ NotImplementedError
735
+ If the shorthand operator for bitwise operators
736
+ (~=, ^=, &=, |=, <<=, >>=) is encountered
737
+
738
+ """
739
+ return self.transform_binary_operator(node)
740
+
741
+ def transform_unary_operator(self, node):
742
+ """Transformation function for handling unary operators
743
+
744
+ Returns
745
+ =======
746
+
747
+ unary_expression: Codegen AST node
748
+ simplified unary expression represented as Codegen AST
749
+
750
+ Raises
751
+ ======
752
+
753
+ NotImplementedError
754
+ If dereferencing operator(*), address operator(&) or
755
+ bitwise NOT operator(~) is encountered
756
+
757
+ """
758
+ # supported operators list
759
+ operators_list = ['+', '-', '++', '--', '!']
760
+ tokens = list(node.get_tokens())
761
+
762
+ # it can be either pre increment/decrement or any other operator from the list
763
+ if tokens[0].spelling in operators_list:
764
+ child = self.transform(next(node.get_children()))
765
+ # (decl_ref) e.g.; int a = ++b; or simply ++b;
766
+ if isinstance(child, str):
767
+ if tokens[0].spelling == '+':
768
+ return Symbol(child)
769
+ if tokens[0].spelling == '-':
770
+ return Mul(Symbol(child), -1)
771
+ if tokens[0].spelling == '++':
772
+ return PreIncrement(Symbol(child))
773
+ if tokens[0].spelling == '--':
774
+ return PreDecrement(Symbol(child))
775
+ if tokens[0].spelling == '!':
776
+ return Not(Symbol(child))
777
+ # e.g.; int a = -1; or int b = -(1 + 2);
778
+ else:
779
+ if tokens[0].spelling == '+':
780
+ return child
781
+ if tokens[0].spelling == '-':
782
+ return Mul(child, -1)
783
+ if tokens[0].spelling == '!':
784
+ return Not(sympify(bool(child)))
785
+
786
+ # it can be either post increment/decrement
787
+ # since variable name is obtained in token[0].spelling
788
+ elif tokens[1].spelling in ['++', '--']:
789
+ child = self.transform(next(node.get_children()))
790
+ if tokens[1].spelling == '++':
791
+ return PostIncrement(Symbol(child))
792
+ if tokens[1].spelling == '--':
793
+ return PostDecrement(Symbol(child))
794
+ else:
795
+ raise NotImplementedError("Dereferencing operator, "
796
+ "Address operator and bitwise NOT operator "
797
+ "have not been implemented yet!")
798
+
799
+ def transform_binary_operator(self, node):
800
+ """Transformation function for handling binary operators
801
+
802
+ Returns
803
+ =======
804
+
805
+ binary_expression: Codegen AST node
806
+ simplified binary expression represented as Codegen AST
807
+
808
+ Raises
809
+ ======
810
+
811
+ NotImplementedError
812
+ If a bitwise operator or
813
+ unary operator(which is a child of any binary
814
+ operator in Clang AST) is encountered
815
+
816
+ """
817
+ # get all the tokens of assignment
818
+ # and store it in the tokens list
819
+ tokens = list(node.get_tokens())
820
+
821
+ # supported operators list
822
+ operators_list = ['+', '-', '*', '/', '%','=',
823
+ '>', '>=', '<', '<=', '==', '!=', '&&', '||', '+=', '-=',
824
+ '*=', '/=', '%=']
825
+
826
+ # this stack will contain variable content
827
+ # and type of variable in the rhs
828
+ combined_variables_stack = []
829
+
830
+ # this stack will contain operators
831
+ # to be processed in the rhs
832
+ operators_stack = []
833
+
834
+ # iterate through every token
835
+ for token in tokens:
836
+ # token is either '(', ')' or
837
+ # any of the supported operators from the operator list
838
+ if token.kind == cin.TokenKind.PUNCTUATION:
839
+
840
+ # push '(' to the operators stack
841
+ if token.spelling == '(':
842
+ operators_stack.append('(')
843
+
844
+ elif token.spelling == ')':
845
+ # keep adding the expression to the
846
+ # combined variables stack unless
847
+ # '(' is found
848
+ while (operators_stack
849
+ and operators_stack[-1] != '('):
850
+ if len(combined_variables_stack) < 2:
851
+ raise NotImplementedError(
852
+ "Unary operators as a part of "
853
+ "binary operators is not "
854
+ "supported yet!")
855
+ rhs = combined_variables_stack.pop()
856
+ lhs = combined_variables_stack.pop()
857
+ operator = operators_stack.pop()
858
+ combined_variables_stack.append(
859
+ self.perform_operation(
860
+ lhs, rhs, operator))
861
+
862
+ # pop '('
863
+ operators_stack.pop()
864
+
865
+ # token is an operator (supported)
866
+ elif token.spelling in operators_list:
867
+ while (operators_stack
868
+ and self.priority_of(token.spelling)
869
+ <= self.priority_of(
870
+ operators_stack[-1])):
871
+ if len(combined_variables_stack) < 2:
872
+ raise NotImplementedError(
873
+ "Unary operators as a part of "
874
+ "binary operators is not "
875
+ "supported yet!")
876
+ rhs = combined_variables_stack.pop()
877
+ lhs = combined_variables_stack.pop()
878
+ operator = operators_stack.pop()
879
+ combined_variables_stack.append(
880
+ self.perform_operation(
881
+ lhs, rhs, operator))
882
+
883
+ # push current operator
884
+ operators_stack.append(token.spelling)
885
+
886
+ # token is a bitwise operator
887
+ elif token.spelling in ['&', '|', '^', '<<', '>>']:
888
+ raise NotImplementedError(
889
+ "Bitwise operator has not been "
890
+ "implemented yet!")
891
+
892
+ # token is a shorthand bitwise operator
893
+ elif token.spelling in ['&=', '|=', '^=', '<<=',
894
+ '>>=']:
895
+ raise NotImplementedError(
896
+ "Shorthand bitwise operator has not been "
897
+ "implemented yet!")
898
+ else:
899
+ raise NotImplementedError(
900
+ "Given token {} is not implemented yet!"
901
+ .format(token.spelling))
902
+
903
+ # token is an identifier(variable)
904
+ elif token.kind == cin.TokenKind.IDENTIFIER:
905
+ combined_variables_stack.append(
906
+ [token.spelling, 'identifier'])
907
+
908
+ # token is a literal
909
+ elif token.kind == cin.TokenKind.LITERAL:
910
+ combined_variables_stack.append(
911
+ [token.spelling, 'literal'])
912
+
913
+ # token is a keyword, either true or false
914
+ elif (token.kind == cin.TokenKind.KEYWORD
915
+ and token.spelling in ['true', 'false']):
916
+ combined_variables_stack.append(
917
+ [token.spelling, 'boolean'])
918
+ else:
919
+ raise NotImplementedError(
920
+ "Given token {} is not implemented yet!"
921
+ .format(token.spelling))
922
+
923
+ # process remaining operators
924
+ while operators_stack:
925
+ if len(combined_variables_stack) < 2:
926
+ raise NotImplementedError(
927
+ "Unary operators as a part of "
928
+ "binary operators is not "
929
+ "supported yet!")
930
+ rhs = combined_variables_stack.pop()
931
+ lhs = combined_variables_stack.pop()
932
+ operator = operators_stack.pop()
933
+ combined_variables_stack.append(
934
+ self.perform_operation(lhs, rhs, operator))
935
+
936
+ return combined_variables_stack[-1][0]
937
+
938
+ def priority_of(self, op):
939
+ """To get the priority of given operator"""
940
+ if op in ['=', '+=', '-=', '*=', '/=', '%=']:
941
+ return 1
942
+ if op in ['&&', '||']:
943
+ return 2
944
+ if op in ['<', '<=', '>', '>=', '==', '!=']:
945
+ return 3
946
+ if op in ['+', '-']:
947
+ return 4
948
+ if op in ['*', '/', '%']:
949
+ return 5
950
+ return 0
951
+
952
+ def perform_operation(self, lhs, rhs, op):
953
+ """Performs operation supported by the SymPy core
954
+
955
+ Returns
956
+ =======
957
+
958
+ combined_variable: list
959
+ contains variable content and type of variable
960
+
961
+ """
962
+ lhs_value = self.get_expr_for_operand(lhs)
963
+ rhs_value = self.get_expr_for_operand(rhs)
964
+ if op == '+':
965
+ return [Add(lhs_value, rhs_value), 'expr']
966
+ if op == '-':
967
+ return [Add(lhs_value, -rhs_value), 'expr']
968
+ if op == '*':
969
+ return [Mul(lhs_value, rhs_value), 'expr']
970
+ if op == '/':
971
+ return [Mul(lhs_value, Pow(rhs_value, Integer(-1))), 'expr']
972
+ if op == '%':
973
+ return [Mod(lhs_value, rhs_value), 'expr']
974
+ if op in ['<', '<=', '>', '>=', '==', '!=']:
975
+ return [Rel(lhs_value, rhs_value, op), 'expr']
976
+ if op == '&&':
977
+ return [And(as_Boolean(lhs_value), as_Boolean(rhs_value)), 'expr']
978
+ if op == '||':
979
+ return [Or(as_Boolean(lhs_value), as_Boolean(rhs_value)), 'expr']
980
+ if op == '=':
981
+ return [Assignment(Variable(lhs_value), rhs_value), 'expr']
982
+ if op in ['+=', '-=', '*=', '/=', '%=']:
983
+ return [aug_assign(Variable(lhs_value), op[0], rhs_value), 'expr']
984
+
985
+ def get_expr_for_operand(self, combined_variable):
986
+ """Gives out SymPy Codegen AST node
987
+
988
+ AST node returned is corresponding to
989
+ combined variable passed.Combined variable contains
990
+ variable content and type of variable
991
+
992
+ """
993
+ if combined_variable[1] == 'identifier':
994
+ return Symbol(combined_variable[0])
995
+ if combined_variable[1] == 'literal':
996
+ if '.' in combined_variable[0]:
997
+ return Float(float(combined_variable[0]))
998
+ else:
999
+ return Integer(int(combined_variable[0]))
1000
+ if combined_variable[1] == 'expr':
1001
+ return combined_variable[0]
1002
+ if combined_variable[1] == 'boolean':
1003
+ return true if combined_variable[0] == 'true' else false
1004
+
1005
+ def transform_null_stmt(self, node):
1006
+ """Handles Null Statement and returns None"""
1007
+ return none
1008
+
1009
+ def transform_while_stmt(self, node):
1010
+ """Transformation function for handling while statement
1011
+
1012
+ Returns
1013
+ =======
1014
+
1015
+ while statement : Codegen AST Node
1016
+ contains the while statement node having condition and
1017
+ statement block
1018
+
1019
+ """
1020
+ children = node.get_children()
1021
+
1022
+ condition = self.transform(next(children))
1023
+ statements = self.transform(next(children))
1024
+
1025
+ if isinstance(statements, list):
1026
+ statement_block = CodeBlock(*statements)
1027
+ else:
1028
+ statement_block = CodeBlock(statements)
1029
+
1030
+ return While(condition, statement_block)
1031
+
1032
+
1033
+
1034
+ else:
1035
+ class CCodeConverter(): # type: ignore
1036
+ def __init__(self, *args, **kwargs):
1037
+ raise ImportError("Module not Installed")
1038
+
1039
+
1040
+ def parse_c(source):
1041
+ """Function for converting a C source code
1042
+
1043
+ The function reads the source code present in the given file and parses it
1044
+ to give out SymPy Expressions
1045
+
1046
+ Returns
1047
+ =======
1048
+
1049
+ src : list
1050
+ List of Python expression strings
1051
+
1052
+ """
1053
+ converter = CCodeConverter()
1054
+ if os.path.exists(source):
1055
+ src = converter.parse(source, flags = [])
1056
+ else:
1057
+ src = converter.parse_str(source, flags = [])
1058
+ return src
lib/python3.12/site-packages/sympy/parsing/latex/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright 2016, latex2sympy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
lib/python3.12/site-packages/sympy/parsing/latex/LaTeX.g4 ADDED
@@ -0,0 +1,312 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ ANTLR4 LaTeX Math Grammar
3
+
4
+ Ported from latex2sympy by @augustt198 https://github.com/augustt198/latex2sympy See license in
5
+ LICENSE.txt
6
+ */
7
+
8
+ /*
9
+ After changing this file, it is necessary to run `python setup.py antlr` in the root directory of
10
+ the repository. This will regenerate the code in `sympy/parsing/latex/_antlr/*.py`.
11
+ */
12
+
13
+ grammar LaTeX;
14
+
15
+ options {
16
+ language = Python3;
17
+ }
18
+
19
+ WS: [ \t\r\n]+ -> skip;
20
+ THINSPACE: ('\\,' | '\\thinspace') -> skip;
21
+ MEDSPACE: ('\\:' | '\\medspace') -> skip;
22
+ THICKSPACE: ('\\;' | '\\thickspace') -> skip;
23
+ QUAD: '\\quad' -> skip;
24
+ QQUAD: '\\qquad' -> skip;
25
+ NEGTHINSPACE: ('\\!' | '\\negthinspace') -> skip;
26
+ NEGMEDSPACE: '\\negmedspace' -> skip;
27
+ NEGTHICKSPACE: '\\negthickspace' -> skip;
28
+ CMD_LEFT: '\\left' -> skip;
29
+ CMD_RIGHT: '\\right' -> skip;
30
+
31
+ IGNORE:
32
+ (
33
+ '\\vrule'
34
+ | '\\vcenter'
35
+ | '\\vbox'
36
+ | '\\vskip'
37
+ | '\\vspace'
38
+ | '\\hfil'
39
+ | '\\*'
40
+ | '\\-'
41
+ | '\\.'
42
+ | '\\/'
43
+ | '\\"'
44
+ | '\\('
45
+ | '\\='
46
+ ) -> skip;
47
+
48
+ ADD: '+';
49
+ SUB: '-';
50
+ MUL: '*';
51
+ DIV: '/';
52
+
53
+ L_PAREN: '(';
54
+ R_PAREN: ')';
55
+ L_BRACE: '{';
56
+ R_BRACE: '}';
57
+ L_BRACE_LITERAL: '\\{';
58
+ R_BRACE_LITERAL: '\\}';
59
+ L_BRACKET: '[';
60
+ R_BRACKET: ']';
61
+
62
+ BAR: '|';
63
+
64
+ R_BAR: '\\right|';
65
+ L_BAR: '\\left|';
66
+
67
+ L_ANGLE: '\\langle';
68
+ R_ANGLE: '\\rangle';
69
+ FUNC_LIM: '\\lim';
70
+ LIM_APPROACH_SYM:
71
+ '\\to'
72
+ | '\\rightarrow'
73
+ | '\\Rightarrow'
74
+ | '\\longrightarrow'
75
+ | '\\Longrightarrow';
76
+ FUNC_INT:
77
+ '\\int'
78
+ | '\\int\\limits';
79
+ FUNC_SUM: '\\sum';
80
+ FUNC_PROD: '\\prod';
81
+
82
+ FUNC_EXP: '\\exp';
83
+ FUNC_LOG: '\\log';
84
+ FUNC_LG: '\\lg';
85
+ FUNC_LN: '\\ln';
86
+ FUNC_SIN: '\\sin';
87
+ FUNC_COS: '\\cos';
88
+ FUNC_TAN: '\\tan';
89
+ FUNC_CSC: '\\csc';
90
+ FUNC_SEC: '\\sec';
91
+ FUNC_COT: '\\cot';
92
+
93
+ FUNC_ARCSIN: '\\arcsin';
94
+ FUNC_ARCCOS: '\\arccos';
95
+ FUNC_ARCTAN: '\\arctan';
96
+ FUNC_ARCCSC: '\\arccsc';
97
+ FUNC_ARCSEC: '\\arcsec';
98
+ FUNC_ARCCOT: '\\arccot';
99
+
100
+ FUNC_SINH: '\\sinh';
101
+ FUNC_COSH: '\\cosh';
102
+ FUNC_TANH: '\\tanh';
103
+ FUNC_ARSINH: '\\arsinh';
104
+ FUNC_ARCOSH: '\\arcosh';
105
+ FUNC_ARTANH: '\\artanh';
106
+
107
+ L_FLOOR: '\\lfloor';
108
+ R_FLOOR: '\\rfloor';
109
+ L_CEIL: '\\lceil';
110
+ R_CEIL: '\\rceil';
111
+
112
+ FUNC_SQRT: '\\sqrt';
113
+ FUNC_OVERLINE: '\\overline';
114
+
115
+ CMD_TIMES: '\\times';
116
+ CMD_CDOT: '\\cdot';
117
+ CMD_DIV: '\\div';
118
+ CMD_FRAC:
119
+ '\\frac'
120
+ | '\\dfrac'
121
+ | '\\tfrac';
122
+ CMD_BINOM: '\\binom';
123
+ CMD_DBINOM: '\\dbinom';
124
+ CMD_TBINOM: '\\tbinom';
125
+
126
+ CMD_MATHIT: '\\mathit';
127
+
128
+ UNDERSCORE: '_';
129
+ CARET: '^';
130
+ COLON: ':';
131
+
132
+ fragment WS_CHAR: [ \t\r\n];
133
+ DIFFERENTIAL: 'd' WS_CHAR*? ([a-zA-Z] | '\\' [a-zA-Z]+);
134
+
135
+ LETTER: [a-zA-Z];
136
+ DIGIT: [0-9];
137
+
138
+ EQUAL: (('&' WS_CHAR*?)? '=') | ('=' (WS_CHAR*? '&')?);
139
+ NEQ: '\\neq';
140
+
141
+ LT: '<';
142
+ LTE: ('\\leq' | '\\le' | LTE_Q | LTE_S);
143
+ LTE_Q: '\\leqq';
144
+ LTE_S: '\\leqslant';
145
+
146
+ GT: '>';
147
+ GTE: ('\\geq' | '\\ge' | GTE_Q | GTE_S);
148
+ GTE_Q: '\\geqq';
149
+ GTE_S: '\\geqslant';
150
+
151
+ BANG: '!';
152
+
153
+ SINGLE_QUOTES: '\''+;
154
+
155
+ SYMBOL: '\\' [a-zA-Z]+;
156
+
157
+ math: relation;
158
+
159
+ relation:
160
+ relation (EQUAL | LT | LTE | GT | GTE | NEQ) relation
161
+ | expr;
162
+
163
+ equality: expr EQUAL expr;
164
+
165
+ expr: additive;
166
+
167
+ additive: additive (ADD | SUB) additive | mp;
168
+
169
+ // mult part
170
+ mp:
171
+ mp (MUL | CMD_TIMES | CMD_CDOT | DIV | CMD_DIV | COLON) mp
172
+ | unary;
173
+
174
+ mp_nofunc:
175
+ mp_nofunc (
176
+ MUL
177
+ | CMD_TIMES
178
+ | CMD_CDOT
179
+ | DIV
180
+ | CMD_DIV
181
+ | COLON
182
+ ) mp_nofunc
183
+ | unary_nofunc;
184
+
185
+ unary: (ADD | SUB) unary | postfix+;
186
+
187
+ unary_nofunc:
188
+ (ADD | SUB) unary_nofunc
189
+ | postfix postfix_nofunc*;
190
+
191
+ postfix: exp postfix_op*;
192
+ postfix_nofunc: exp_nofunc postfix_op*;
193
+ postfix_op: BANG | eval_at;
194
+
195
+ eval_at:
196
+ BAR (eval_at_sup | eval_at_sub | eval_at_sup eval_at_sub);
197
+
198
+ eval_at_sub: UNDERSCORE L_BRACE (expr | equality) R_BRACE;
199
+
200
+ eval_at_sup: CARET L_BRACE (expr | equality) R_BRACE;
201
+
202
+ exp: exp CARET (atom | L_BRACE expr R_BRACE) subexpr? | comp;
203
+
204
+ exp_nofunc:
205
+ exp_nofunc CARET (atom | L_BRACE expr R_BRACE) subexpr?
206
+ | comp_nofunc;
207
+
208
+ comp:
209
+ group
210
+ | abs_group
211
+ | func
212
+ | atom
213
+ | floor
214
+ | ceil;
215
+
216
+ comp_nofunc:
217
+ group
218
+ | abs_group
219
+ | atom
220
+ | floor
221
+ | ceil;
222
+
223
+ group:
224
+ L_PAREN expr R_PAREN
225
+ | L_BRACKET expr R_BRACKET
226
+ | L_BRACE expr R_BRACE
227
+ | L_BRACE_LITERAL expr R_BRACE_LITERAL;
228
+
229
+ abs_group: BAR expr BAR;
230
+
231
+ number: DIGIT+ (',' DIGIT DIGIT DIGIT)* ('.' DIGIT+)?;
232
+
233
+ atom: (LETTER | SYMBOL) (subexpr? SINGLE_QUOTES? | SINGLE_QUOTES? subexpr?)
234
+ | number
235
+ | DIFFERENTIAL
236
+ | mathit
237
+ | frac
238
+ | binom
239
+ | bra
240
+ | ket;
241
+
242
+ bra: L_ANGLE expr (R_BAR | BAR);
243
+ ket: (L_BAR | BAR) expr R_ANGLE;
244
+
245
+ mathit: CMD_MATHIT L_BRACE mathit_text R_BRACE;
246
+ mathit_text: LETTER*;
247
+
248
+ frac: CMD_FRAC (upperd = DIGIT | L_BRACE upper = expr R_BRACE)
249
+ (lowerd = DIGIT | L_BRACE lower = expr R_BRACE);
250
+
251
+ binom:
252
+ (CMD_BINOM | CMD_DBINOM | CMD_TBINOM) L_BRACE n = expr R_BRACE L_BRACE k = expr R_BRACE;
253
+
254
+ floor: L_FLOOR val = expr R_FLOOR;
255
+ ceil: L_CEIL val = expr R_CEIL;
256
+
257
+ func_normal:
258
+ FUNC_EXP
259
+ | FUNC_LOG
260
+ | FUNC_LG
261
+ | FUNC_LN
262
+ | FUNC_SIN
263
+ | FUNC_COS
264
+ | FUNC_TAN
265
+ | FUNC_CSC
266
+ | FUNC_SEC
267
+ | FUNC_COT
268
+ | FUNC_ARCSIN
269
+ | FUNC_ARCCOS
270
+ | FUNC_ARCTAN
271
+ | FUNC_ARCCSC
272
+ | FUNC_ARCSEC
273
+ | FUNC_ARCCOT
274
+ | FUNC_SINH
275
+ | FUNC_COSH
276
+ | FUNC_TANH
277
+ | FUNC_ARSINH
278
+ | FUNC_ARCOSH
279
+ | FUNC_ARTANH;
280
+
281
+ func:
282
+ func_normal (subexpr? supexpr? | supexpr? subexpr?) (
283
+ L_PAREN func_arg R_PAREN
284
+ | func_arg_noparens
285
+ )
286
+ | (LETTER | SYMBOL) (subexpr? SINGLE_QUOTES? | SINGLE_QUOTES? subexpr?) // e.g. f(x), f_1'(x)
287
+ L_PAREN args R_PAREN
288
+ | FUNC_INT (subexpr supexpr | supexpr subexpr)? (
289
+ additive? DIFFERENTIAL
290
+ | frac
291
+ | additive
292
+ )
293
+ | FUNC_SQRT (L_BRACKET root = expr R_BRACKET)? L_BRACE base = expr R_BRACE
294
+ | FUNC_OVERLINE L_BRACE base = expr R_BRACE
295
+ | (FUNC_SUM | FUNC_PROD) (subeq supexpr | supexpr subeq) mp
296
+ | FUNC_LIM limit_sub mp;
297
+
298
+ args: (expr ',' args) | expr;
299
+
300
+ limit_sub:
301
+ UNDERSCORE L_BRACE (LETTER | SYMBOL) LIM_APPROACH_SYM expr (
302
+ CARET ((L_BRACE (ADD | SUB) R_BRACE) | ADD | SUB)
303
+ )? R_BRACE;
304
+
305
+ func_arg: expr | (expr ',' func_arg);
306
+ func_arg_noparens: mp_nofunc;
307
+
308
+ subexpr: UNDERSCORE (atom | L_BRACE expr R_BRACE);
309
+ supexpr: CARET (atom | L_BRACE expr R_BRACE);
310
+
311
+ subeq: UNDERSCORE L_BRACE equality R_BRACE;
312
+ supeq: UNDERSCORE L_BRACE equality R_BRACE;
lib/python3.12/site-packages/sympy/parsing/latex/__init__.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.external import import_module
2
+ from sympy.utilities.decorator import doctest_depends_on
3
+
4
+ from sympy.parsing.latex.lark import LarkLaTeXParser, TransformToSymPyExpr, parse_latex_lark # noqa
5
+
6
+ from .errors import LaTeXParsingError # noqa
7
+
8
+
9
+ __doctest_requires__ = {('parse_latex',): ['antlr4', 'lark']}
10
+
11
+
12
+ @doctest_depends_on(modules=('antlr4', 'lark'))
13
+ def parse_latex(s, strict=False, backend="antlr"):
14
+ r"""Converts the input LaTeX string ``s`` to a SymPy ``Expr``.
15
+
16
+ Parameters
17
+ ==========
18
+
19
+ s : str
20
+ The LaTeX string to parse. In Python source containing LaTeX,
21
+ *raw strings* (denoted with ``r"``, like this one) are preferred,
22
+ as LaTeX makes liberal use of the ``\`` character, which would
23
+ trigger escaping in normal Python strings.
24
+ backend : str, optional
25
+ Currently, there are two backends supported: ANTLR, and Lark.
26
+ The default setting is to use the ANTLR backend, which can be
27
+ changed to Lark if preferred.
28
+
29
+ Use ``backend="antlr"`` for the ANTLR-based parser, and
30
+ ``backend="lark"`` for the Lark-based parser.
31
+
32
+ The ``backend`` option is case-sensitive, and must be in
33
+ all lowercase.
34
+ strict : bool, optional
35
+ This option is only available with the ANTLR backend.
36
+
37
+ If True, raise an exception if the string cannot be parsed as
38
+ valid LaTeX. If False, try to recover gracefully from common
39
+ mistakes.
40
+
41
+ Examples
42
+ ========
43
+
44
+ >>> from sympy.parsing.latex import parse_latex
45
+ >>> expr = parse_latex(r"\frac {1 + \sqrt {\a}} {\b}")
46
+ >>> expr
47
+ (sqrt(a) + 1)/b
48
+ >>> expr.evalf(4, subs=dict(a=5, b=2))
49
+ 1.618
50
+ >>> func = parse_latex(r"\int_1^\alpha \dfrac{\mathrm{d}t}{t}", backend="lark")
51
+ >>> func.evalf(subs={"alpha": 2})
52
+ 0.693147180559945
53
+ """
54
+
55
+ if backend == "antlr":
56
+ _latex = import_module(
57
+ 'sympy.parsing.latex._parse_latex_antlr',
58
+ import_kwargs={'fromlist': ['X']})
59
+
60
+ if _latex is not None:
61
+ return _latex.parse_latex(s, strict)
62
+ elif backend == "lark":
63
+ return parse_latex_lark(s)
64
+ else:
65
+ raise NotImplementedError(f"Using the '{backend}' backend in the LaTeX" \
66
+ " parser is not supported.")
lib/python3.12/site-packages/sympy/parsing/latex/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (2.63 kB). View file
 
lib/python3.12/site-packages/sympy/parsing/latex/__pycache__/_build_latex_antlr.cpython-312.pyc ADDED
Binary file (4.6 kB). View file
 
lib/python3.12/site-packages/sympy/parsing/latex/__pycache__/_parse_latex_antlr.cpython-312.pyc ADDED
Binary file (31.6 kB). View file
 
lib/python3.12/site-packages/sympy/parsing/latex/__pycache__/errors.cpython-312.pyc ADDED
Binary file (390 Bytes). View file
 
lib/python3.12/site-packages/sympy/parsing/latex/_antlr/__init__.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ # *** GENERATED BY `setup.py antlr`, DO NOT EDIT BY HAND ***
2
+ #
3
+ # Generated from ../LaTeX.g4, derived from latex2sympy
4
+ # latex2sympy is licensed under the MIT license
5
+ # https://github.com/augustt198/latex2sympy/blob/master/LICENSE.txt
6
+ #
7
+ # Generated with antlr4
8
+ # antlr4 is licensed under the BSD-3-Clause License
9
+ # https://github.com/antlr/antlr4/blob/master/LICENSE.txt
lib/python3.12/site-packages/sympy/parsing/latex/_antlr/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (205 Bytes). View file