onnxslim 0.1.80__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. onnxslim/__init__.py +16 -0
  2. onnxslim/__main__.py +4 -0
  3. onnxslim/argparser.py +215 -0
  4. onnxslim/cli/__init__.py +1 -0
  5. onnxslim/cli/_main.py +180 -0
  6. onnxslim/core/__init__.py +219 -0
  7. onnxslim/core/optimization/__init__.py +146 -0
  8. onnxslim/core/optimization/dead_node_elimination.py +151 -0
  9. onnxslim/core/optimization/subexpression_elimination.py +76 -0
  10. onnxslim/core/optimization/weight_tying.py +59 -0
  11. onnxslim/core/pattern/__init__.py +249 -0
  12. onnxslim/core/pattern/elimination/__init__.py +5 -0
  13. onnxslim/core/pattern/elimination/concat.py +61 -0
  14. onnxslim/core/pattern/elimination/reshape.py +77 -0
  15. onnxslim/core/pattern/elimination/reshape_as.py +64 -0
  16. onnxslim/core/pattern/elimination/slice.py +108 -0
  17. onnxslim/core/pattern/elimination/unsqueeze.py +92 -0
  18. onnxslim/core/pattern/fusion/__init__.py +8 -0
  19. onnxslim/core/pattern/fusion/concat_reshape.py +50 -0
  20. onnxslim/core/pattern/fusion/convadd.py +70 -0
  21. onnxslim/core/pattern/fusion/convbn.py +86 -0
  22. onnxslim/core/pattern/fusion/convmul.py +69 -0
  23. onnxslim/core/pattern/fusion/gelu.py +47 -0
  24. onnxslim/core/pattern/fusion/gemm.py +330 -0
  25. onnxslim/core/pattern/fusion/padconv.py +89 -0
  26. onnxslim/core/pattern/fusion/reduce.py +67 -0
  27. onnxslim/core/pattern/registry.py +28 -0
  28. onnxslim/misc/__init__.py +0 -0
  29. onnxslim/misc/tabulate.py +2681 -0
  30. onnxslim/third_party/__init__.py +0 -0
  31. onnxslim/third_party/_sympy/__init__.py +0 -0
  32. onnxslim/third_party/_sympy/functions.py +205 -0
  33. onnxslim/third_party/_sympy/numbers.py +397 -0
  34. onnxslim/third_party/_sympy/printers.py +491 -0
  35. onnxslim/third_party/_sympy/solve.py +172 -0
  36. onnxslim/third_party/_sympy/symbol.py +102 -0
  37. onnxslim/third_party/onnx_graphsurgeon/__init__.py +15 -0
  38. onnxslim/third_party/onnx_graphsurgeon/exporters/__init__.py +1 -0
  39. onnxslim/third_party/onnx_graphsurgeon/exporters/base_exporter.py +33 -0
  40. onnxslim/third_party/onnx_graphsurgeon/exporters/onnx_exporter.py +432 -0
  41. onnxslim/third_party/onnx_graphsurgeon/graph_pattern/__init__.py +4 -0
  42. onnxslim/third_party/onnx_graphsurgeon/graph_pattern/graph_pattern.py +466 -0
  43. onnxslim/third_party/onnx_graphsurgeon/importers/__init__.py +1 -0
  44. onnxslim/third_party/onnx_graphsurgeon/importers/base_importer.py +33 -0
  45. onnxslim/third_party/onnx_graphsurgeon/importers/onnx_importer.py +558 -0
  46. onnxslim/third_party/onnx_graphsurgeon/ir/__init__.py +0 -0
  47. onnxslim/third_party/onnx_graphsurgeon/ir/function.py +274 -0
  48. onnxslim/third_party/onnx_graphsurgeon/ir/graph.py +1575 -0
  49. onnxslim/third_party/onnx_graphsurgeon/ir/node.py +266 -0
  50. onnxslim/third_party/onnx_graphsurgeon/ir/tensor.py +504 -0
  51. onnxslim/third_party/onnx_graphsurgeon/logger/__init__.py +1 -0
  52. onnxslim/third_party/onnx_graphsurgeon/logger/logger.py +261 -0
  53. onnxslim/third_party/onnx_graphsurgeon/util/__init__.py +0 -0
  54. onnxslim/third_party/onnx_graphsurgeon/util/exception.py +20 -0
  55. onnxslim/third_party/onnx_graphsurgeon/util/misc.py +252 -0
  56. onnxslim/third_party/symbolic_shape_infer.py +3273 -0
  57. onnxslim/utils.py +794 -0
  58. onnxslim/version.py +1 -0
  59. onnxslim-0.1.80.dist-info/METADATA +207 -0
  60. onnxslim-0.1.80.dist-info/RECORD +65 -0
  61. onnxslim-0.1.80.dist-info/WHEEL +5 -0
  62. onnxslim-0.1.80.dist-info/entry_points.txt +2 -0
  63. onnxslim-0.1.80.dist-info/licenses/LICENSE +21 -0
  64. onnxslim-0.1.80.dist-info/top_level.txt +1 -0
  65. onnxslim-0.1.80.dist-info/zip-safe +1 -0
File without changes
File without changes
@@ -0,0 +1,205 @@
1
+ # mypy: allow-untyped-defs
2
+ from __future__ import annotations
3
+
4
+ import functools
5
+ import math
6
+ from typing import TYPE_CHECKING
7
+
8
+ import sympy
9
+ from sympy.core.numbers import equal_valued
10
+ from sympy.printing.precedence import PRECEDENCE
11
+
12
+ from .numbers import int_oo
13
+
14
+ if TYPE_CHECKING:
15
+ from collections.abc import Iterable
16
+
17
+ # Portions of this file are adapted from the Sympy codebase, which was
18
+ # licensed as follows:
19
+ #
20
+ # Copyright (c) 2006-2023 SymPy Development Team
21
+ #
22
+ # All rights reserved.
23
+ #
24
+ # Redistribution and use in source and binary forms, with or without
25
+ # modification, are permitted provided that the following conditions are met:
26
+ #
27
+ # a. Redistributions of source code must retain the above copyright notice,
28
+ # this list of conditions and the following disclaimer.
29
+ # b. Redistributions in binary form must reproduce the above copyright
30
+ # notice, this list of conditions and the following disclaimer in the
31
+ # documentation and/or other materials provided with the distribution.
32
+ # c. Neither the name of SymPy nor the names of its contributors
33
+ # may be used to endorse or promote products derived from this software
34
+ # without specific prior written permission.
35
+ #
36
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
37
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
40
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
42
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
43
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
44
+ # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
45
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46
+ # DAMAGE.
47
+
48
+
49
+ def simple_floordiv_gcd(p: sympy.Basic, q: sympy.Basic) -> sympy.Basic:
50
+ """
51
+ Fast path for sympy.gcd, using a simple factoring strategy.
52
+
53
+ We try to rewrite p and q in the form n*e*p1 + n*e*p2 and n*e*q0, where n is the greatest common integer factor and
54
+ e is the largest syntactic common factor (i.e., common sub-expression) in p and q. Then the gcd returned is n*e,
55
+ canceling which we would be left with p1 + p2 and q0.
56
+
57
+ Note that further factoring of p1 + p2 and q0 might be possible with sympy.factor (which uses domain-specific
58
+ theories). E.g., we are unable to find that x*y + x + y + 1 is divisible by x + 1. More generally, when q is of the
59
+ form q1 + q2 (instead of being already factored) it might be necessary to fall back on sympy.gcd.
60
+ """
61
+
62
+ def integer_coefficient(x: sympy.Basic) -> int:
63
+ integer_coefficients: list[int] = [
64
+ abs(int(arg)) for arg in sympy.Mul.make_args(x) if isinstance(arg, (int, sympy.Integer))
65
+ ]
66
+ return math.prod(integer_coefficients)
67
+
68
+ def integer_factor(expr: sympy.Basic) -> int:
69
+ integer_factors: Iterable[int] = map(integer_coefficient, sympy.Add.make_args(expr))
70
+ return functools.reduce(math.gcd, integer_factors)
71
+
72
+ gcd: int = math.gcd(integer_factor(p), integer_factor(q))
73
+ p, q = p / gcd, q / gcd # type: ignore[operator, assignment] # remove in py3.12
74
+
75
+ base_splits: list[tuple[sympy.Basic, ...]] = list(map(sympy.Mul.make_args, sympy.Add.make_args(p)))
76
+ divisor_split: tuple[sympy.Basic, ...] = sympy.Mul.make_args(q)
77
+ for x in divisor_split:
78
+ if all(x in base_split for base_split in base_splits):
79
+ gcd = gcd * x # type: ignore[operator] # remove in py3.12
80
+ return gcd # type: ignore[return-value] # remove in py3.12
81
+
82
+
83
+ # It would be nice to have assertions on whether or not inputs is_integer
84
+ # However, with bugs like https://github.com/sympy/sympy/issues/26620 sympy
85
+ # sometimes inconsistently reports floats an integers.
86
+ #
87
+ # What we can assume from sympy is that if something is an int, it
88
+ # definitely is is_integer, but if it is a float it may or may not
89
+ # be is_integer. So we are unable to do strong asserts that things
90
+ # are NOT integers.
91
+
92
+
93
+ # TODO: In Triton, // rounds to zero, but in Python, it is floor division.
94
+ # When we can prove both arguments are non-negative, we should just have a
95
+ # GenericFloorDiv (name pending) which can codegen efficiently in Python/C,
96
+ # and then PythonFloorDiv and CIntDiv which have the appropriate rounding
97
+ # semantics.
98
+ #
99
+ # Right now, FloorDiv de facto changes behavior if arguments are negative or
100
+ # not, this can potentially cause correctness issues.
101
+ class FloorDiv(sympy.Function):
102
+ """
103
+ We maintain this so that:
104
+ 1. We can use divisibility guards to simplify FloorDiv(a, b) to a / b.
105
+ 2. Printing out the expression is nicer (compared to say, representing a//b as (a - a % b) / b).
106
+
107
+ NB: This is Python-style floor division, round to -Inf
108
+ """
109
+
110
+ nargs: tuple[int, ...] = (2,)
111
+ precedence: int = 35 # lower precedence than add
112
+ is_integer: bool = True
113
+
114
+ @property
115
+ def base(self) -> sympy.Basic:
116
+ return self.args[0]
117
+
118
+ @property
119
+ def divisor(self) -> sympy.Basic:
120
+ return self.args[1]
121
+
122
+ def _sympystr(self, printer: sympy.printing.StrPrinter) -> str:
123
+ base = printer.parenthesize(self.base, PRECEDENCE["Atom"] - 0.5)
124
+ divisor = printer.parenthesize(self.divisor, PRECEDENCE["Atom"] - 0.5)
125
+ return f"({base}//{divisor})"
126
+
127
+ # Automatic evaluation.
128
+ # https://docs.sympy.org/latest/guides/custom-functions.html#best-practices-for-eval
129
+ @classmethod
130
+ def eval(cls, base: sympy.Integer, divisor: sympy.Integer) -> sympy.Basic | None:
131
+ # python test/test_dynamic_shapes.py -k TestDimConstraints.test_dim_constraints_solve_full
132
+ # Assert triggered by inequality solver
133
+ # assert base.is_integer, base
134
+ # assert divisor.is_integer, divisor
135
+
136
+ # We don't provide the same error message as in Python because SymPy
137
+ # makes it difficult to check the types.
138
+ if divisor.is_zero:
139
+ raise ZeroDivisionError("division by zero")
140
+ if base in (int_oo, -int_oo, sympy.oo, -sympy.oo) and divisor in (
141
+ int_oo,
142
+ -int_oo,
143
+ sympy.oo,
144
+ -sympy.oo,
145
+ ):
146
+ return sympy.nan
147
+ if base is sympy.nan or divisor is sympy.nan:
148
+ return sympy.nan
149
+
150
+ if base.is_zero:
151
+ return sympy.S.Zero
152
+ if base.is_integer and equal_valued(divisor, 1):
153
+ return base
154
+ if base.is_integer and equal_valued(divisor, -1):
155
+ return sympy.Mul(base, -1)
156
+ if (
157
+ isinstance(base, sympy.Number)
158
+ and isinstance(divisor, sympy.Number)
159
+ and (base in (int_oo, -int_oo, sympy.oo, -sympy.oo) or divisor in (int_oo, -int_oo, sympy.oo, -sympy.oo))
160
+ ):
161
+ r = float(base) / float(divisor)
162
+ if r == math.inf:
163
+ return int_oo
164
+ elif r == -math.inf:
165
+ return -int_oo
166
+ elif math.isnan(r):
167
+ return sympy.nan
168
+ else:
169
+ return sympy.Integer(math.floor(r))
170
+ if isinstance(base, sympy.Integer) and isinstance(divisor, sympy.Integer):
171
+ return sympy.Integer(int(base) // int(divisor))
172
+ if isinstance(base, FloorDiv):
173
+ return FloorDiv(base.args[0], base.args[1] * divisor)
174
+
175
+ # Expands (x + y) // b into x // b + y // b.
176
+ # This only works if floor is an identity, i.e. x / b is an integer.
177
+ if isinstance(divisor, sympy.Integer):
178
+ quotients = 0
179
+ terms = []
180
+ for term in sympy.Add.make_args(base):
181
+ quotient = term / divisor
182
+
183
+ if quotient.is_integer:
184
+ terms.append(term)
185
+ quotients += quotient
186
+
187
+ if len(terms) != 0:
188
+ # Passing evaluate = False since expression will be optimized during the subtraction post its construction.
189
+ return FloorDiv(base - sympy.Add(*terms, evaluate=False), divisor) + quotients
190
+
191
+ try:
192
+ gcd = simple_floordiv_gcd(base, divisor)
193
+ if equal_valued(gcd, 1) and isinstance(divisor, sympy.Add):
194
+ gcd = sympy.gcd(base, divisor)
195
+ if not equal_valued(gcd, 1):
196
+ return FloorDiv(sympy.simplify(base / gcd), sympy.simplify(divisor / gcd))
197
+ except sympy.PolynomialError:
198
+ pass # https://github.com/pytorch/pytorch/issues/108276
199
+
200
+ return None
201
+
202
+ def _ccode(self, printer):
203
+ base = printer.parenthesize(self.base, PRECEDENCE["Atom"] - 0.5)
204
+ divisor = printer.parenthesize(self.divisor, PRECEDENCE["Atom"] - 0.5)
205
+ return f"floor({base}/{divisor})"
@@ -0,0 +1,397 @@
1
+ # mypy: allow-untyped-defs
2
+ from __future__ import annotations
3
+
4
+ import mpmath.libmp as mlib # type: ignore[import-untyped]
5
+ import sympy
6
+ from sympy import Expr
7
+ from sympy.core.decorators import _sympifyit
8
+ from sympy.core.expr import AtomicExpr
9
+ from sympy.core.numbers import Number
10
+ from sympy.core.parameters import global_parameters
11
+ from sympy.core.singleton import S, Singleton
12
+
13
+
14
+ class IntInfinitySlim(Number, metaclass=Singleton):
15
+ r"""
16
+ Positive integer infinite quantity.
17
+
18
+ Integer infinity is a value in an extended integers which
19
+ is greater than all other integers. We distinguish it from
20
+ sympy's existing notion of infinity in that it reports that
21
+ it is_integer.
22
+
23
+ Infinity is a singleton, and can be accessed by ``S.IntInfinitySlim``,
24
+ or can be imported as ``int_oo``.
25
+ """
26
+
27
+ # NB: We can't actually mark this as infinite, as integer and infinite are
28
+ # inconsistent assumptions in sympy. We also report that we are complex,
29
+ # different from sympy.oo
30
+
31
+ is_integer = True
32
+ is_commutative = True
33
+ is_number = True
34
+ is_extended_real = True
35
+ is_comparable = True
36
+ is_extended_positive = True
37
+ is_prime = False
38
+
39
+ # Ensure we get dispatched to before plain numbers
40
+ _op_priority = 100.0
41
+
42
+ __slots__ = ()
43
+
44
+ def __new__(cls):
45
+ return AtomicExpr.__new__(cls)
46
+
47
+ def _sympystr(self, printer):
48
+ return "int_oo"
49
+
50
+ def _eval_subs(self, old, new):
51
+ if self == old:
52
+ return new
53
+
54
+ # We could do these, not sure about it
55
+ """
56
+ def _eval_evalf(self, prec=None):
57
+ return Float('inf')
58
+
59
+ def evalf(self, prec=None, **options):
60
+ return self._eval_evalf(prec)
61
+ """
62
+
63
+ @_sympifyit("other", NotImplemented)
64
+ def __add__(self, other):
65
+ if isinstance(other, Number) and global_parameters.evaluate:
66
+ if other in (S.Infinity, S.NegativeInfinity):
67
+ return other
68
+ if other in (S.NegativeIntInfinitySlim, S.NaN):
69
+ return S.NaN
70
+ return self
71
+ return Number.__add__(self, other)
72
+
73
+ __radd__ = __add__
74
+
75
+ @_sympifyit("other", NotImplemented)
76
+ def __sub__(self, other):
77
+ if isinstance(other, Number) and global_parameters.evaluate:
78
+ if other is S.Infinity:
79
+ return S.NegativeInfinity
80
+ if other is S.NegativeInfinity:
81
+ return S.Infinity
82
+ if other in (S.IntInfinitySlim, S.NaN):
83
+ return S.NaN
84
+ return self
85
+ return Number.__sub__(self, other)
86
+
87
+ @_sympifyit("other", NotImplemented)
88
+ def __rsub__(self, other):
89
+ return (-self).__add__(other)
90
+
91
+ @_sympifyit("other", NotImplemented)
92
+ def __mul__(self, other):
93
+ if isinstance(other, Number) and global_parameters.evaluate:
94
+ if other.is_zero or other is S.NaN:
95
+ return S.NaN
96
+ if other.is_extended_positive:
97
+ return self
98
+ return S.NegativeIntInfinitySlim
99
+ return Number.__mul__(self, other)
100
+
101
+ __rmul__ = __mul__
102
+
103
+ @_sympifyit("other", NotImplemented)
104
+ def __truediv__(self, other):
105
+ if isinstance(other, Number) and global_parameters.evaluate:
106
+ if other in (
107
+ S.Infinity,
108
+ S.IntInfinitySlim,
109
+ S.NegativeInfinity,
110
+ S.NegativeIntInfinitySlim,
111
+ S.NaN,
112
+ ):
113
+ return S.NaN
114
+ if other.is_extended_nonnegative:
115
+ return S.Infinity # truediv produces float
116
+ return S.NegativeInfinity # truediv produces float
117
+ return Number.__truediv__(self, other)
118
+
119
+ def __abs__(self):
120
+ return S.IntInfinitySlim
121
+
122
+ def __neg__(self):
123
+ return S.NegativeIntInfinitySlim
124
+
125
+ def _eval_power(self, expt):
126
+ if expt.is_extended_positive:
127
+ return S.IntInfinitySlim
128
+ if expt.is_extended_negative:
129
+ return S.Zero
130
+ if expt is S.NaN:
131
+ return S.NaN
132
+ if expt is S.ComplexInfinity:
133
+ return S.NaN
134
+ if expt.is_extended_real is False and expt.is_number:
135
+ from sympy.functions.elementary.complexes import re
136
+
137
+ expt_real = re(expt)
138
+ if expt_real.is_positive:
139
+ return S.ComplexInfinity
140
+ if expt_real.is_negative:
141
+ return S.Zero
142
+ if expt_real.is_zero:
143
+ return S.NaN
144
+
145
+ return self ** expt.evalf()
146
+
147
+ def _as_mpf_val(self, prec):
148
+ return mlib.finf
149
+
150
+ def __hash__(self):
151
+ return super().__hash__()
152
+
153
+ def __eq__(self, other):
154
+ return other is S.IntInfinitySlim
155
+
156
+ def __ne__(self, other):
157
+ return other is not S.IntInfinitySlim
158
+
159
+ def __gt__(self, other):
160
+ if other is S.Infinity:
161
+ return sympy.false # sympy.oo > int_oo
162
+ elif other is S.IntInfinitySlim:
163
+ return sympy.false # consistency with sympy.oo
164
+ else:
165
+ return sympy.true
166
+
167
+ def __ge__(self, other):
168
+ if other is S.Infinity:
169
+ return sympy.false # sympy.oo > int_oo
170
+ elif other is S.IntInfinitySlim:
171
+ return sympy.true # consistency with sympy.oo
172
+ else:
173
+ return sympy.true
174
+
175
+ def __lt__(self, other):
176
+ if other is S.Infinity:
177
+ return sympy.true # sympy.oo > int_oo
178
+ elif other is S.IntInfinitySlim:
179
+ return sympy.false # consistency with sympy.oo
180
+ else:
181
+ return sympy.false
182
+
183
+ def __le__(self, other):
184
+ if other is S.Infinity:
185
+ return sympy.true # sympy.oo > int_oo
186
+ elif other is S.IntInfinitySlim:
187
+ return sympy.true # consistency with sympy.oo
188
+ else:
189
+ return sympy.false
190
+
191
+ @_sympifyit("other", NotImplemented)
192
+ def __mod__(self, other):
193
+ if not isinstance(other, Expr):
194
+ return NotImplemented
195
+ return S.NaN
196
+
197
+ __rmod__ = __mod__
198
+
199
+ def floor(self):
200
+ return self
201
+
202
+ def ceiling(self):
203
+ return self
204
+
205
+
206
+ int_oo = S.IntInfinitySlim
207
+
208
+
209
+ class NegativeIntInfinitySlim(Number, metaclass=Singleton):
210
+ """
211
+ Negative integer infinite quantity.
212
+
213
+ NegativeInfinity is a singleton, and can be accessed
214
+ by ``S.NegativeInfinity``.
215
+
216
+ See Also
217
+ ========
218
+
219
+ IntInfinitySlim
220
+ """
221
+
222
+ # Ensure we get dispatched to before plain numbers
223
+ _op_priority = 100.0
224
+
225
+ is_integer = True
226
+ is_extended_real = True
227
+ is_commutative = True
228
+ is_comparable = True
229
+ is_extended_negative = True
230
+ is_number = True
231
+ is_prime = False
232
+
233
+ __slots__ = ()
234
+
235
+ def __new__(cls):
236
+ return AtomicExpr.__new__(cls)
237
+
238
+ def _eval_subs(self, old, new):
239
+ if self == old:
240
+ return new
241
+
242
+ def _sympystr(self, printer):
243
+ return "-int_oo"
244
+
245
+ """
246
+ def _eval_evalf(self, prec=None):
247
+ return Float('-inf')
248
+
249
+ def evalf(self, prec=None, **options):
250
+ return self._eval_evalf(prec)
251
+ """
252
+
253
+ @_sympifyit("other", NotImplemented)
254
+ def __add__(self, other):
255
+ if isinstance(other, Number) and global_parameters.evaluate:
256
+ if other is S.Infinity:
257
+ return S.Infinity
258
+ if other in (S.IntInfinitySlim, S.NaN):
259
+ return S.NaN
260
+ return self
261
+ return Number.__add__(self, other)
262
+
263
+ __radd__ = __add__
264
+
265
+ @_sympifyit("other", NotImplemented)
266
+ def __sub__(self, other):
267
+ if isinstance(other, Number) and global_parameters.evaluate:
268
+ if other is S.NegativeInfinity:
269
+ return S.Infinity
270
+ if other in (S.NegativeIntInfinitySlim, S.NaN):
271
+ return S.NaN
272
+ return self
273
+ return Number.__sub__(self, other)
274
+
275
+ @_sympifyit("other", NotImplemented)
276
+ def __rsub__(self, other):
277
+ return (-self).__add__(other)
278
+
279
+ @_sympifyit("other", NotImplemented)
280
+ def __mul__(self, other):
281
+ if isinstance(other, Number) and global_parameters.evaluate:
282
+ if other.is_zero or other is S.NaN:
283
+ return S.NaN
284
+ if other.is_extended_positive:
285
+ return self
286
+ return S.IntInfinitySlim
287
+ return Number.__mul__(self, other)
288
+
289
+ __rmul__ = __mul__
290
+
291
+ @_sympifyit("other", NotImplemented)
292
+ def __truediv__(self, other):
293
+ if isinstance(other, Number) and global_parameters.evaluate:
294
+ if other in (
295
+ S.Infinity,
296
+ S.IntInfinitySlim,
297
+ S.NegativeInfinity,
298
+ S.NegativeIntInfinitySlim,
299
+ S.NaN,
300
+ ):
301
+ return S.NaN
302
+ if other.is_extended_nonnegative:
303
+ return self
304
+ return S.Infinity # truediv returns float
305
+ return Number.__truediv__(self, other)
306
+
307
+ def __abs__(self):
308
+ return S.IntInfinitySlim
309
+
310
+ def __neg__(self):
311
+ return S.IntInfinitySlim
312
+
313
+ def _eval_power(self, expt):
314
+ if expt.is_number:
315
+ if expt in (
316
+ S.NaN,
317
+ S.Infinity,
318
+ S.NegativeInfinity,
319
+ S.IntInfinitySlim,
320
+ S.NegativeIntInfinitySlim,
321
+ ):
322
+ return S.NaN
323
+
324
+ if isinstance(expt, sympy.Integer) and expt.is_extended_positive:
325
+ if expt.is_odd:
326
+ return S.NegativeIntInfinitySlim
327
+ else:
328
+ return S.IntInfinitySlim
329
+
330
+ inf_part = S.IntInfinitySlim**expt
331
+ s_part = S.NegativeOne**expt
332
+ if inf_part == 0 and s_part.is_finite:
333
+ return inf_part
334
+ if inf_part is S.ComplexInfinity and s_part.is_finite and not s_part.is_zero:
335
+ return S.ComplexInfinity
336
+ return s_part * inf_part
337
+
338
+ def _as_mpf_val(self, prec):
339
+ return mlib.fninf
340
+
341
+ def __hash__(self):
342
+ return super().__hash__()
343
+
344
+ def __eq__(self, other):
345
+ return other is S.NegativeIntInfinitySlim
346
+
347
+ def __ne__(self, other):
348
+ return other is not S.NegativeIntInfinitySlim
349
+
350
+ def __gt__(self, other):
351
+ if other is S.NegativeInfinity:
352
+ return sympy.true # -sympy.oo < -int_oo
353
+ elif other is S.NegativeIntInfinitySlim:
354
+ return sympy.false # consistency with sympy.oo
355
+ else:
356
+ return sympy.false
357
+
358
+ def __ge__(self, other):
359
+ if other is S.NegativeInfinity:
360
+ return sympy.true # -sympy.oo < -int_oo
361
+ elif other is S.NegativeIntInfinitySlim:
362
+ return sympy.true # consistency with sympy.oo
363
+ else:
364
+ return sympy.false
365
+
366
+ def __lt__(self, other):
367
+ if other is S.NegativeInfinity:
368
+ return sympy.false # -sympy.oo < -int_oo
369
+ elif other is S.NegativeIntInfinitySlim:
370
+ return sympy.false # consistency with sympy.oo
371
+ else:
372
+ return sympy.true
373
+
374
+ def __le__(self, other):
375
+ if other is S.NegativeInfinity:
376
+ return sympy.false # -sympy.oo < -int_oo
377
+ elif other is S.NegativeIntInfinitySlim:
378
+ return sympy.true # consistency with sympy.oo
379
+ else:
380
+ return sympy.true
381
+
382
+ @_sympifyit("other", NotImplemented)
383
+ def __mod__(self, other):
384
+ if not isinstance(other, Expr):
385
+ return NotImplemented
386
+ return S.NaN
387
+
388
+ __rmod__ = __mod__
389
+
390
+ def floor(self):
391
+ return self
392
+
393
+ def ceiling(self):
394
+ return self
395
+
396
+ def as_powers_dict(self):
397
+ return {S.NegativeOne: 1, S.IntInfinitySlim: 1}