1from sympy.assumptions import Predicate
2from sympy.multipledispatch import Dispatcher
3
4
5class 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
38class RationalPredicate(Predicate):
39    """
40    Rational number predicate.
41
42    Explanation
43    ===========
44
45    ``Q.rational(x)`` is true iff ``x`` belongs to the set of
46    rational numbers.
47
48    Examples
49    ========
50
51    >>> from sympy import ask, Q, pi, S
52    >>> ask(Q.rational(0))
53    True
54    >>> ask(Q.rational(S(1)/2))
55    True
56    >>> ask(Q.rational(pi))
57    False
58
59    References
60    ==========
61
62    https://en.wikipedia.org/wiki/Rational_number
63
64    """
65    name = 'rational'
66    handler = Dispatcher(
67        "RationalHandler",
68        doc=("Handler for Q.rational.\n\n"
69        "Test that an expression belongs to the field of rational numbers.")
70    )
71
72
73class IrrationalPredicate(Predicate):
74    """
75    Irrational number predicate.
76
77    Explanation
78    ===========
79
80    ``Q.irrational(x)`` is true iff ``x``  is any real number that
81    cannot be expressed as a ratio of integers.
82
83    Examples
84    ========
85
86    >>> from sympy import ask, Q, pi, S, I
87    >>> ask(Q.irrational(0))
88    False
89    >>> ask(Q.irrational(S(1)/2))
90    False
91    >>> ask(Q.irrational(pi))
92    True
93    >>> ask(Q.irrational(I))
94    False
95
96    References
97    ==========
98
99    .. [1] https://en.wikipedia.org/wiki/Irrational_number
100
101    """
102    name = 'irrational'
103    handler = Dispatcher(
104        "IrrationalHandler",
105        doc=("Handler for Q.irrational.\n\n"
106        "Test that an expression is irrational numbers.")
107    )
108
109
110class RealPredicate(Predicate):
111    r"""
112    Real number predicate.
113
114    Explanation
115    ===========
116
117    ``Q.real(x)`` is true iff ``x`` is a real number, i.e., it is in the
118    interval `(-\infty, \infty)`.  Note that, in particular the
119    infinities are not real. Use ``Q.extended_real`` if you want to
120    consider those as well.
121
122    A few important facts about reals:
123
124    - Every real number is positive, negative, or zero.  Furthermore,
125        because these sets are pairwise disjoint, each real number is
126        exactly one of those three.
127
128    - Every real number is also complex.
129
130    - Every real number is finite.
131
132    - Every real number is either rational or irrational.
133
134    - Every real number is either algebraic or transcendental.
135
136    - The facts ``Q.negative``, ``Q.zero``, ``Q.positive``,
137        ``Q.nonnegative``, ``Q.nonpositive``, ``Q.nonzero``,
138        ``Q.integer``, ``Q.rational``, and ``Q.irrational`` all imply
139        ``Q.real``, as do all facts that imply those facts.
140
141    - The facts ``Q.algebraic``, and ``Q.transcendental`` do not imply
142        ``Q.real``; they imply ``Q.complex``. An algebraic or
143        transcendental number may or may not be real.
144
145    - The "non" facts (i.e., ``Q.nonnegative``, ``Q.nonzero``,
146        ``Q.nonpositive`` and ``Q.noninteger``) are not equivalent to
147        not the fact, but rather, not the fact *and* ``Q.real``.
148        For example, ``Q.nonnegative`` means ``~Q.negative & Q.real``.
149        So for example, ``I`` is not nonnegative, nonzero, or
150        nonpositive.
151
152    Examples
153    ========
154
155    >>> from sympy import Q, ask, symbols
156    >>> x = symbols('x')
157    >>> ask(Q.real(x), Q.positive(x))
158    True
159    >>> ask(Q.real(0))
160    True
161
162    References
163    ==========
164
165    .. [1] https://en.wikipedia.org/wiki/Real_number
166
167    """
168    name = 'real'
169    handler = Dispatcher(
170        "RealHandler",
171        doc=("Handler for Q.real.\n\n"
172        "Test that an expression belongs to the field of real numbers.")
173    )
174
175
176class ExtendedRealPredicate(Predicate):
177    r"""
178    Extended real predicate.
179
180    Explanation
181    ===========
182
183    ``Q.extended_real(x)`` is true iff ``x`` is a real number or
184    `\{-\infty, \infty\}`.
185
186    See documentation of ``Q.real`` for more information about related
187    facts.
188
189    Examples
190    ========
191
192    >>> from sympy import ask, Q, oo, I
193    >>> ask(Q.extended_real(1))
194    True
195    >>> ask(Q.extended_real(I))
196    False
197    >>> ask(Q.extended_real(oo))
198    True
199
200    """
201    name = 'extended_real'
202    handler = Dispatcher(
203        "ExtendedRealHandler",
204        doc=("Handler for Q.extended_real.\n\n"
205        "Test that an expression belongs to the field of extended real\n"
206        "numbers, that is real numbers union {Infinity, -Infinity}.")
207    )
208
209
210class HermitianPredicate(Predicate):
211    """
212    Hermitian predicate.
213
214    Explanation
215    ===========
216
217    ``ask(Q.hermitian(x))`` is true iff ``x`` belongs to the set of
218    Hermitian operators.
219
220    References
221    ==========
222
223    .. [1] http://mathworld.wolfram.com/HermitianOperator.html
224
225    """
226    # TODO: Add examples
227    name = 'hermitian'
228    handler = Dispatcher(
229        "HermitianHandler",
230        doc=("Handler for Q.hermitian.\n\n"
231        "Test that an expression belongs to the field of Hermitian operators.")
232    )
233
234
235class ComplexPredicate(Predicate):
236    """
237    Complex number predicate.
238
239    Explanation
240    ===========
241
242    ``Q.complex(x)`` is true iff ``x`` belongs to the set of complex
243    numbers. Note that every complex number is finite.
244
245    Examples
246    ========
247
248    >>> from sympy import Q, Symbol, ask, I, oo
249    >>> x = Symbol('x')
250    >>> ask(Q.complex(0))
251    True
252    >>> ask(Q.complex(2 + 3*I))
253    True
254    >>> ask(Q.complex(oo))
255    False
256
257    References
258    ==========
259
260    .. [1] https://en.wikipedia.org/wiki/Complex_number
261
262    """
263    name = 'complex'
264    handler = Dispatcher(
265        "ComplexHandler",
266        doc=("Handler for Q.complex.\n\n"
267        "Test that an expression belongs to the field of complex numbers.")
268    )
269
270
271class ImaginaryPredicate(Predicate):
272    """
273    Imaginary number predicate.
274
275    Explanation
276    ===========
277
278    ``Q.imaginary(x)`` is true iff ``x`` can be written as a real
279    number multiplied by the imaginary unit ``I``. Please note that ``0``
280    is not considered to be an imaginary number.
281
282    Examples
283    ========
284
285    >>> from sympy import Q, ask, I
286    >>> ask(Q.imaginary(3*I))
287    True
288    >>> ask(Q.imaginary(2 + 3*I))
289    False
290    >>> ask(Q.imaginary(0))
291    False
292
293    References
294    ==========
295
296    .. [1] https://en.wikipedia.org/wiki/Imaginary_number
297
298    """
299    name = 'imaginary'
300    handler = Dispatcher(
301        "ImaginaryHandler",
302        doc=("Handler for Q.imaginary.\n\n"
303        "Test that an expression belongs to the field of imaginary numbers,\n"
304        "that is, numbers in the form x*I, where x is real.")
305    )
306
307
308class AntihermitianPredicate(Predicate):
309    """
310    Antihermitian predicate.
311
312    Explanation
313    ===========
314
315    ``Q.antihermitian(x)`` is true iff ``x`` belongs to the field of
316    antihermitian operators, i.e., operators in the form ``x*I``, where
317    ``x`` is Hermitian.
318
319    References
320    ==========
321
322    .. [1] http://mathworld.wolfram.com/HermitianOperator.html
323
324    """
325    # TODO: Add examples
326    name = 'antihermitian'
327    handler = Dispatcher(
328        "AntiHermitianHandler",
329        doc=("Handler for Q.antihermitian.\n\n"
330        "Test that an expression belongs to the field of anti-Hermitian\n"
331        "operators, that is, operators in the form x*I, where x is Hermitian.")
332    )
333
334
335class AlgebraicPredicate(Predicate):
336    r"""
337    Algebraic number predicate.
338
339    Explanation
340    ===========
341
342    ``Q.algebraic(x)`` is true iff ``x`` belongs to the set of
343    algebraic numbers. ``x`` is algebraic if there is some polynomial
344    in ``p(x)\in \mathbb\{Q\}[x]`` such that ``p(x) = 0``.
345
346    Examples
347    ========
348
349    >>> from sympy import ask, Q, sqrt, I, pi
350    >>> ask(Q.algebraic(sqrt(2)))
351    True
352    >>> ask(Q.algebraic(I))
353    True
354    >>> ask(Q.algebraic(pi))
355    False
356
357    References
358    ==========
359
360    .. [1] https://en.wikipedia.org/wiki/Algebraic_number
361
362    """
363    name = 'algebraic'
364    AlgebraicHandler = Dispatcher(
365        "AlgebraicHandler",
366        doc="""Handler for Q.algebraic key."""
367    )
368
369
370class TranscendentalPredicate(Predicate):
371    """
372    Transcedental number predicate.
373
374    Explanation
375    ===========
376
377    ``Q.transcendental(x)`` is true iff ``x`` belongs to the set of
378    transcendental numbers. A transcendental number is a real
379    or complex number that is not algebraic.
380
381    """
382    # TODO: Add examples
383    name = 'transcendental'
384    handler = Dispatcher(
385        "Transcendental",
386        doc="""Handler for Q.transcendental key."""
387    )
388