Coverage for /usr/lib/python3/dist-packages/sympy/functions/elementary/miscellaneous.py: 31%
317 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1from sympy.core import Function, S, sympify, NumberKind
2from sympy.utilities.iterables import sift
3from sympy.core.add import Add
4from sympy.core.containers import Tuple
5from sympy.core.operations import LatticeOp, ShortCircuit
6from sympy.core.function import (Application, Lambda,
7 ArgumentIndexError)
8from sympy.core.expr import Expr
9from sympy.core.exprtools import factor_terms
10from sympy.core.mod import Mod
11from sympy.core.mul import Mul
12from sympy.core.numbers import Rational
13from sympy.core.power import Pow
14from sympy.core.relational import Eq, Relational
15from sympy.core.singleton import Singleton
16from sympy.core.sorting import ordered
17from sympy.core.symbol import Dummy
18from sympy.core.rules import Transform
19from sympy.core.logic import fuzzy_and, fuzzy_or, _torf
20from sympy.core.traversal import walk
21from sympy.core.numbers import Integer
22from sympy.logic.boolalg import And, Or
25def _minmax_as_Piecewise(op, *args):
26 # helper for Min/Max rewrite as Piecewise
27 from sympy.functions.elementary.piecewise import Piecewise
28 ec = []
29 for i, a in enumerate(args):
30 c = [Relational(a, args[j], op) for j in range(i + 1, len(args))]
31 ec.append((a, And(*c)))
32 return Piecewise(*ec)
35class IdentityFunction(Lambda, metaclass=Singleton):
36 """
37 The identity function
39 Examples
40 ========
42 >>> from sympy import Id, Symbol
43 >>> x = Symbol('x')
44 >>> Id(x)
45 x
47 """
49 _symbol = Dummy('x')
51 @property
52 def signature(self):
53 return Tuple(self._symbol)
55 @property
56 def expr(self):
57 return self._symbol
60Id = S.IdentityFunction
62###############################################################################
63############################# ROOT and SQUARE ROOT FUNCTION ###################
64###############################################################################
67def sqrt(arg, evaluate=None):
68 """Returns the principal square root.
70 Parameters
71 ==========
73 evaluate : bool, optional
74 The parameter determines if the expression should be evaluated.
75 If ``None``, its value is taken from
76 ``global_parameters.evaluate``.
78 Examples
79 ========
81 >>> from sympy import sqrt, Symbol, S
82 >>> x = Symbol('x')
84 >>> sqrt(x)
85 sqrt(x)
87 >>> sqrt(x)**2
88 x
90 Note that sqrt(x**2) does not simplify to x.
92 >>> sqrt(x**2)
93 sqrt(x**2)
95 This is because the two are not equal to each other in general.
96 For example, consider x == -1:
98 >>> from sympy import Eq
99 >>> Eq(sqrt(x**2), x).subs(x, -1)
100 False
102 This is because sqrt computes the principal square root, so the square may
103 put the argument in a different branch. This identity does hold if x is
104 positive:
106 >>> y = Symbol('y', positive=True)
107 >>> sqrt(y**2)
108 y
110 You can force this simplification by using the powdenest() function with
111 the force option set to True:
113 >>> from sympy import powdenest
114 >>> sqrt(x**2)
115 sqrt(x**2)
116 >>> powdenest(sqrt(x**2), force=True)
117 x
119 To get both branches of the square root you can use the rootof function:
121 >>> from sympy import rootof
123 >>> [rootof(x**2-3,i) for i in (0,1)]
124 [-sqrt(3), sqrt(3)]
126 Although ``sqrt`` is printed, there is no ``sqrt`` function so looking for
127 ``sqrt`` in an expression will fail:
129 >>> from sympy.utilities.misc import func_name
130 >>> func_name(sqrt(x))
131 'Pow'
132 >>> sqrt(x).has(sqrt)
133 False
135 To find ``sqrt`` look for ``Pow`` with an exponent of ``1/2``:
137 >>> (x + 1/sqrt(x)).find(lambda i: i.is_Pow and abs(i.exp) is S.Half)
138 {1/sqrt(x)}
140 See Also
141 ========
143 sympy.polys.rootoftools.rootof, root, real_root
145 References
146 ==========
148 .. [1] https://en.wikipedia.org/wiki/Square_root
149 .. [2] https://en.wikipedia.org/wiki/Principal_value
150 """
151 # arg = sympify(arg) is handled by Pow
152 return Pow(arg, S.Half, evaluate=evaluate)
155def cbrt(arg, evaluate=None):
156 """Returns the principal cube root.
158 Parameters
159 ==========
161 evaluate : bool, optional
162 The parameter determines if the expression should be evaluated.
163 If ``None``, its value is taken from
164 ``global_parameters.evaluate``.
166 Examples
167 ========
169 >>> from sympy import cbrt, Symbol
170 >>> x = Symbol('x')
172 >>> cbrt(x)
173 x**(1/3)
175 >>> cbrt(x)**3
176 x
178 Note that cbrt(x**3) does not simplify to x.
180 >>> cbrt(x**3)
181 (x**3)**(1/3)
183 This is because the two are not equal to each other in general.
184 For example, consider `x == -1`:
186 >>> from sympy import Eq
187 >>> Eq(cbrt(x**3), x).subs(x, -1)
188 False
190 This is because cbrt computes the principal cube root, this
191 identity does hold if `x` is positive:
193 >>> y = Symbol('y', positive=True)
194 >>> cbrt(y**3)
195 y
197 See Also
198 ========
200 sympy.polys.rootoftools.rootof, root, real_root
202 References
203 ==========
205 .. [1] https://en.wikipedia.org/wiki/Cube_root
206 .. [2] https://en.wikipedia.org/wiki/Principal_value
208 """
209 return Pow(arg, Rational(1, 3), evaluate=evaluate)
212def root(arg, n, k=0, evaluate=None):
213 r"""Returns the *k*-th *n*-th root of ``arg``.
215 Parameters
216 ==========
218 k : int, optional
219 Should be an integer in $\{0, 1, ..., n-1\}$.
220 Defaults to the principal root if $0$.
222 evaluate : bool, optional
223 The parameter determines if the expression should be evaluated.
224 If ``None``, its value is taken from
225 ``global_parameters.evaluate``.
227 Examples
228 ========
230 >>> from sympy import root, Rational
231 >>> from sympy.abc import x, n
233 >>> root(x, 2)
234 sqrt(x)
236 >>> root(x, 3)
237 x**(1/3)
239 >>> root(x, n)
240 x**(1/n)
242 >>> root(x, -Rational(2, 3))
243 x**(-3/2)
245 To get the k-th n-th root, specify k:
247 >>> root(-2, 3, 2)
248 -(-1)**(2/3)*2**(1/3)
250 To get all n n-th roots you can use the rootof function.
251 The following examples show the roots of unity for n
252 equal 2, 3 and 4:
254 >>> from sympy import rootof
256 >>> [rootof(x**2 - 1, i) for i in range(2)]
257 [-1, 1]
259 >>> [rootof(x**3 - 1,i) for i in range(3)]
260 [1, -1/2 - sqrt(3)*I/2, -1/2 + sqrt(3)*I/2]
262 >>> [rootof(x**4 - 1,i) for i in range(4)]
263 [-1, 1, -I, I]
265 SymPy, like other symbolic algebra systems, returns the
266 complex root of negative numbers. This is the principal
267 root and differs from the text-book result that one might
268 be expecting. For example, the cube root of -8 does not
269 come back as -2:
271 >>> root(-8, 3)
272 2*(-1)**(1/3)
274 The real_root function can be used to either make the principal
275 result real (or simply to return the real root directly):
277 >>> from sympy import real_root
278 >>> real_root(_)
279 -2
280 >>> real_root(-32, 5)
281 -2
283 Alternatively, the n//2-th n-th root of a negative number can be
284 computed with root:
286 >>> root(-32, 5, 5//2)
287 -2
289 See Also
290 ========
292 sympy.polys.rootoftools.rootof
293 sympy.core.power.integer_nthroot
294 sqrt, real_root
296 References
297 ==========
299 .. [1] https://en.wikipedia.org/wiki/Square_root
300 .. [2] https://en.wikipedia.org/wiki/Real_root
301 .. [3] https://en.wikipedia.org/wiki/Root_of_unity
302 .. [4] https://en.wikipedia.org/wiki/Principal_value
303 .. [5] https://mathworld.wolfram.com/CubeRoot.html
305 """
306 n = sympify(n)
307 if k:
308 return Mul(Pow(arg, S.One/n, evaluate=evaluate), S.NegativeOne**(2*k/n), evaluate=evaluate)
309 return Pow(arg, 1/n, evaluate=evaluate)
312def real_root(arg, n=None, evaluate=None):
313 r"""Return the real *n*'th-root of *arg* if possible.
315 Parameters
316 ==========
318 n : int or None, optional
319 If *n* is ``None``, then all instances of
320 $(-n)^{1/\text{odd}}$ will be changed to $-n^{1/\text{odd}}$.
321 This will only create a real root of a principal root.
322 The presence of other factors may cause the result to not be
323 real.
325 evaluate : bool, optional
326 The parameter determines if the expression should be evaluated.
327 If ``None``, its value is taken from
328 ``global_parameters.evaluate``.
330 Examples
331 ========
333 >>> from sympy import root, real_root
335 >>> real_root(-8, 3)
336 -2
337 >>> root(-8, 3)
338 2*(-1)**(1/3)
339 >>> real_root(_)
340 -2
342 If one creates a non-principal root and applies real_root, the
343 result will not be real (so use with caution):
345 >>> root(-8, 3, 2)
346 -2*(-1)**(2/3)
347 >>> real_root(_)
348 -2*(-1)**(2/3)
350 See Also
351 ========
353 sympy.polys.rootoftools.rootof
354 sympy.core.power.integer_nthroot
355 root, sqrt
356 """
357 from sympy.functions.elementary.complexes import Abs, im, sign
358 from sympy.functions.elementary.piecewise import Piecewise
359 if n is not None:
360 return Piecewise(
361 (root(arg, n, evaluate=evaluate), Or(Eq(n, S.One), Eq(n, S.NegativeOne))),
362 (Mul(sign(arg), root(Abs(arg), n, evaluate=evaluate), evaluate=evaluate),
363 And(Eq(im(arg), S.Zero), Eq(Mod(n, 2), S.One))),
364 (root(arg, n, evaluate=evaluate), True))
365 rv = sympify(arg)
366 n1pow = Transform(lambda x: -(-x.base)**x.exp,
367 lambda x:
368 x.is_Pow and
369 x.base.is_negative and
370 x.exp.is_Rational and
371 x.exp.p == 1 and x.exp.q % 2)
372 return rv.xreplace(n1pow)
374###############################################################################
375############################# MINIMUM and MAXIMUM #############################
376###############################################################################
379class MinMaxBase(Expr, LatticeOp):
380 def __new__(cls, *args, **assumptions):
381 from sympy.core.parameters import global_parameters
382 evaluate = assumptions.pop('evaluate', global_parameters.evaluate)
383 args = (sympify(arg) for arg in args)
385 # first standard filter, for cls.zero and cls.identity
386 # also reshape Max(a, Max(b, c)) to Max(a, b, c)
388 if evaluate:
389 try:
390 args = frozenset(cls._new_args_filter(args))
391 except ShortCircuit:
392 return cls.zero
393 # remove redundant args that are easily identified
394 args = cls._collapse_arguments(args, **assumptions)
395 # find local zeros
396 args = cls._find_localzeros(args, **assumptions)
397 args = frozenset(args)
399 if not args:
400 return cls.identity
402 if len(args) == 1:
403 return list(args).pop()
405 # base creation
406 obj = Expr.__new__(cls, *ordered(args), **assumptions)
407 obj._argset = args
408 return obj
410 @classmethod
411 def _collapse_arguments(cls, args, **assumptions):
412 """Remove redundant args.
414 Examples
415 ========
417 >>> from sympy import Min, Max
418 >>> from sympy.abc import a, b, c, d, e
420 Any arg in parent that appears in any
421 parent-like function in any of the flat args
422 of parent can be removed from that sub-arg:
424 >>> Min(a, Max(b, Min(a, c, d)))
425 Min(a, Max(b, Min(c, d)))
427 If the arg of parent appears in an opposite-than parent
428 function in any of the flat args of parent that function
429 can be replaced with the arg:
431 >>> Min(a, Max(b, Min(c, d, Max(a, e))))
432 Min(a, Max(b, Min(a, c, d)))
433 """
434 if not args:
435 return args
436 args = list(ordered(args))
437 if cls == Min:
438 other = Max
439 else:
440 other = Min
442 # find global comparable max of Max and min of Min if a new
443 # value is being introduced in these args at position 0 of
444 # the ordered args
445 if args[0].is_number:
446 sifted = mins, maxs = [], []
447 for i in args:
448 for v in walk(i, Min, Max):
449 if v.args[0].is_comparable:
450 sifted[isinstance(v, Max)].append(v)
451 small = Min.identity
452 for i in mins:
453 v = i.args[0]
454 if v.is_number and (v < small) == True:
455 small = v
456 big = Max.identity
457 for i in maxs:
458 v = i.args[0]
459 if v.is_number and (v > big) == True:
460 big = v
461 # at the point when this function is called from __new__,
462 # there may be more than one numeric arg present since
463 # local zeros have not been handled yet, so look through
464 # more than the first arg
465 if cls == Min:
466 for arg in args:
467 if not arg.is_number:
468 break
469 if (arg < small) == True:
470 small = arg
471 elif cls == Max:
472 for arg in args:
473 if not arg.is_number:
474 break
475 if (arg > big) == True:
476 big = arg
477 T = None
478 if cls == Min:
479 if small != Min.identity:
480 other = Max
481 T = small
482 elif big != Max.identity:
483 other = Min
484 T = big
485 if T is not None:
486 # remove numerical redundancy
487 for i in range(len(args)):
488 a = args[i]
489 if isinstance(a, other):
490 a0 = a.args[0]
491 if ((a0 > T) if other == Max else (a0 < T)) == True:
492 args[i] = cls.identity
494 # remove redundant symbolic args
495 def do(ai, a):
496 if not isinstance(ai, (Min, Max)):
497 return ai
498 cond = a in ai.args
499 if not cond:
500 return ai.func(*[do(i, a) for i in ai.args],
501 evaluate=False)
502 if isinstance(ai, cls):
503 return ai.func(*[do(i, a) for i in ai.args if i != a],
504 evaluate=False)
505 return a
506 for i, a in enumerate(args):
507 args[i + 1:] = [do(ai, a) for ai in args[i + 1:]]
509 # factor out common elements as for
510 # Min(Max(x, y), Max(x, z)) -> Max(x, Min(y, z))
511 # and vice versa when swapping Min/Max -- do this only for the
512 # easy case where all functions contain something in common;
513 # trying to find some optimal subset of args to modify takes
514 # too long
516 def factor_minmax(args):
517 is_other = lambda arg: isinstance(arg, other)
518 other_args, remaining_args = sift(args, is_other, binary=True)
519 if not other_args:
520 return args
522 # Min(Max(x, y, z), Max(x, y, u, v)) -> {x,y}, ({z}, {u,v})
523 arg_sets = [set(arg.args) for arg in other_args]
524 common = set.intersection(*arg_sets)
525 if not common:
526 return args
528 new_other_args = list(common)
529 arg_sets_diff = [arg_set - common for arg_set in arg_sets]
531 # If any set is empty after removing common then all can be
532 # discarded e.g. Min(Max(a, b, c), Max(a, b)) -> Max(a, b)
533 if all(arg_sets_diff):
534 other_args_diff = [other(*s, evaluate=False) for s in arg_sets_diff]
535 new_other_args.append(cls(*other_args_diff, evaluate=False))
537 other_args_factored = other(*new_other_args, evaluate=False)
538 return remaining_args + [other_args_factored]
540 if len(args) > 1:
541 args = factor_minmax(args)
543 return args
545 @classmethod
546 def _new_args_filter(cls, arg_sequence):
547 """
548 Generator filtering args.
550 first standard filter, for cls.zero and cls.identity.
551 Also reshape ``Max(a, Max(b, c))`` to ``Max(a, b, c)``,
552 and check arguments for comparability
553 """
554 for arg in arg_sequence:
555 # pre-filter, checking comparability of arguments
556 if not isinstance(arg, Expr) or arg.is_extended_real is False or (
557 arg.is_number and
558 not arg.is_comparable):
559 raise ValueError("The argument '%s' is not comparable." % arg)
561 if arg == cls.zero:
562 raise ShortCircuit(arg)
563 elif arg == cls.identity:
564 continue
565 elif arg.func == cls:
566 yield from arg.args
567 else:
568 yield arg
570 @classmethod
571 def _find_localzeros(cls, values, **options):
572 """
573 Sequentially allocate values to localzeros.
575 When a value is identified as being more extreme than another member it
576 replaces that member; if this is never true, then the value is simply
577 appended to the localzeros.
578 """
579 localzeros = set()
580 for v in values:
581 is_newzero = True
582 localzeros_ = list(localzeros)
583 for z in localzeros_:
584 if id(v) == id(z):
585 is_newzero = False
586 else:
587 con = cls._is_connected(v, z)
588 if con:
589 is_newzero = False
590 if con is True or con == cls:
591 localzeros.remove(z)
592 localzeros.update([v])
593 if is_newzero:
594 localzeros.update([v])
595 return localzeros
597 @classmethod
598 def _is_connected(cls, x, y):
599 """
600 Check if x and y are connected somehow.
601 """
602 for i in range(2):
603 if x == y:
604 return True
605 t, f = Max, Min
606 for op in "><":
607 for j in range(2):
608 try:
609 if op == ">":
610 v = x >= y
611 else:
612 v = x <= y
613 except TypeError:
614 return False # non-real arg
615 if not v.is_Relational:
616 return t if v else f
617 t, f = f, t
618 x, y = y, x
619 x, y = y, x # run next pass with reversed order relative to start
620 # simplification can be expensive, so be conservative
621 # in what is attempted
622 x = factor_terms(x - y)
623 y = S.Zero
625 return False
627 def _eval_derivative(self, s):
628 # f(x).diff(s) -> x.diff(s) * f.fdiff(1)(s)
629 i = 0
630 l = []
631 for a in self.args:
632 i += 1
633 da = a.diff(s)
634 if da.is_zero:
635 continue
636 try:
637 df = self.fdiff(i)
638 except ArgumentIndexError:
639 df = Function.fdiff(self, i)
640 l.append(df * da)
641 return Add(*l)
643 def _eval_rewrite_as_Abs(self, *args, **kwargs):
644 from sympy.functions.elementary.complexes import Abs
645 s = (args[0] + self.func(*args[1:]))/2
646 d = abs(args[0] - self.func(*args[1:]))/2
647 return (s + d if isinstance(self, Max) else s - d).rewrite(Abs)
649 def evalf(self, n=15, **options):
650 return self.func(*[a.evalf(n, **options) for a in self.args])
652 def n(self, *args, **kwargs):
653 return self.evalf(*args, **kwargs)
655 _eval_is_algebraic = lambda s: _torf(i.is_algebraic for i in s.args)
656 _eval_is_antihermitian = lambda s: _torf(i.is_antihermitian for i in s.args)
657 _eval_is_commutative = lambda s: _torf(i.is_commutative for i in s.args)
658 _eval_is_complex = lambda s: _torf(i.is_complex for i in s.args)
659 _eval_is_composite = lambda s: _torf(i.is_composite for i in s.args)
660 _eval_is_even = lambda s: _torf(i.is_even for i in s.args)
661 _eval_is_finite = lambda s: _torf(i.is_finite for i in s.args)
662 _eval_is_hermitian = lambda s: _torf(i.is_hermitian for i in s.args)
663 _eval_is_imaginary = lambda s: _torf(i.is_imaginary for i in s.args)
664 _eval_is_infinite = lambda s: _torf(i.is_infinite for i in s.args)
665 _eval_is_integer = lambda s: _torf(i.is_integer for i in s.args)
666 _eval_is_irrational = lambda s: _torf(i.is_irrational for i in s.args)
667 _eval_is_negative = lambda s: _torf(i.is_negative for i in s.args)
668 _eval_is_noninteger = lambda s: _torf(i.is_noninteger for i in s.args)
669 _eval_is_nonnegative = lambda s: _torf(i.is_nonnegative for i in s.args)
670 _eval_is_nonpositive = lambda s: _torf(i.is_nonpositive for i in s.args)
671 _eval_is_nonzero = lambda s: _torf(i.is_nonzero for i in s.args)
672 _eval_is_odd = lambda s: _torf(i.is_odd for i in s.args)
673 _eval_is_polar = lambda s: _torf(i.is_polar for i in s.args)
674 _eval_is_positive = lambda s: _torf(i.is_positive for i in s.args)
675 _eval_is_prime = lambda s: _torf(i.is_prime for i in s.args)
676 _eval_is_rational = lambda s: _torf(i.is_rational for i in s.args)
677 _eval_is_real = lambda s: _torf(i.is_real for i in s.args)
678 _eval_is_extended_real = lambda s: _torf(i.is_extended_real for i in s.args)
679 _eval_is_transcendental = lambda s: _torf(i.is_transcendental for i in s.args)
680 _eval_is_zero = lambda s: _torf(i.is_zero for i in s.args)
683class Max(MinMaxBase, Application):
684 r"""
685 Return, if possible, the maximum value of the list.
687 When number of arguments is equal one, then
688 return this argument.
690 When number of arguments is equal two, then
691 return, if possible, the value from (a, b) that is $\ge$ the other.
693 In common case, when the length of list greater than 2, the task
694 is more complicated. Return only the arguments, which are greater
695 than others, if it is possible to determine directional relation.
697 If is not possible to determine such a relation, return a partially
698 evaluated result.
700 Assumptions are used to make the decision too.
702 Also, only comparable arguments are permitted.
704 It is named ``Max`` and not ``max`` to avoid conflicts
705 with the built-in function ``max``.
708 Examples
709 ========
711 >>> from sympy import Max, Symbol, oo
712 >>> from sympy.abc import x, y, z
713 >>> p = Symbol('p', positive=True)
714 >>> n = Symbol('n', negative=True)
716 >>> Max(x, -2)
717 Max(-2, x)
718 >>> Max(x, -2).subs(x, 3)
719 3
720 >>> Max(p, -2)
721 p
722 >>> Max(x, y)
723 Max(x, y)
724 >>> Max(x, y) == Max(y, x)
725 True
726 >>> Max(x, Max(y, z))
727 Max(x, y, z)
728 >>> Max(n, 8, p, 7, -oo)
729 Max(8, p)
730 >>> Max (1, x, oo)
731 oo
733 * Algorithm
735 The task can be considered as searching of supremums in the
736 directed complete partial orders [1]_.
738 The source values are sequentially allocated by the isolated subsets
739 in which supremums are searched and result as Max arguments.
741 If the resulted supremum is single, then it is returned.
743 The isolated subsets are the sets of values which are only the comparable
744 with each other in the current set. E.g. natural numbers are comparable with
745 each other, but not comparable with the `x` symbol. Another example: the
746 symbol `x` with negative assumption is comparable with a natural number.
748 Also there are "least" elements, which are comparable with all others,
749 and have a zero property (maximum or minimum for all elements).
750 For example, in case of $\infty$, the allocation operation is terminated
751 and only this value is returned.
753 Assumption:
754 - if $A > B > C$ then $A > C$
755 - if $A = B$ then $B$ can be removed
757 References
758 ==========
760 .. [1] https://en.wikipedia.org/wiki/Directed_complete_partial_order
761 .. [2] https://en.wikipedia.org/wiki/Lattice_%28order%29
763 See Also
764 ========
766 Min : find minimum values
767 """
768 zero = S.Infinity
769 identity = S.NegativeInfinity
771 def fdiff( self, argindex ):
772 from sympy.functions.special.delta_functions import Heaviside
773 n = len(self.args)
774 if 0 < argindex and argindex <= n:
775 argindex -= 1
776 if n == 2:
777 return Heaviside(self.args[argindex] - self.args[1 - argindex])
778 newargs = tuple([self.args[i] for i in range(n) if i != argindex])
779 return Heaviside(self.args[argindex] - Max(*newargs))
780 else:
781 raise ArgumentIndexError(self, argindex)
783 def _eval_rewrite_as_Heaviside(self, *args, **kwargs):
784 from sympy.functions.special.delta_functions import Heaviside
785 return Add(*[j*Mul(*[Heaviside(j - i) for i in args if i!=j]) \
786 for j in args])
788 def _eval_rewrite_as_Piecewise(self, *args, **kwargs):
789 return _minmax_as_Piecewise('>=', *args)
791 def _eval_is_positive(self):
792 return fuzzy_or(a.is_positive for a in self.args)
794 def _eval_is_nonnegative(self):
795 return fuzzy_or(a.is_nonnegative for a in self.args)
797 def _eval_is_negative(self):
798 return fuzzy_and(a.is_negative for a in self.args)
801class Min(MinMaxBase, Application):
802 """
803 Return, if possible, the minimum value of the list.
804 It is named ``Min`` and not ``min`` to avoid conflicts
805 with the built-in function ``min``.
807 Examples
808 ========
810 >>> from sympy import Min, Symbol, oo
811 >>> from sympy.abc import x, y
812 >>> p = Symbol('p', positive=True)
813 >>> n = Symbol('n', negative=True)
815 >>> Min(x, -2)
816 Min(-2, x)
817 >>> Min(x, -2).subs(x, 3)
818 -2
819 >>> Min(p, -3)
820 -3
821 >>> Min(x, y)
822 Min(x, y)
823 >>> Min(n, 8, p, -7, p, oo)
824 Min(-7, n)
826 See Also
827 ========
829 Max : find maximum values
830 """
831 zero = S.NegativeInfinity
832 identity = S.Infinity
834 def fdiff( self, argindex ):
835 from sympy.functions.special.delta_functions import Heaviside
836 n = len(self.args)
837 if 0 < argindex and argindex <= n:
838 argindex -= 1
839 if n == 2:
840 return Heaviside( self.args[1-argindex] - self.args[argindex] )
841 newargs = tuple([ self.args[i] for i in range(n) if i != argindex])
842 return Heaviside( Min(*newargs) - self.args[argindex] )
843 else:
844 raise ArgumentIndexError(self, argindex)
846 def _eval_rewrite_as_Heaviside(self, *args, **kwargs):
847 from sympy.functions.special.delta_functions import Heaviside
848 return Add(*[j*Mul(*[Heaviside(i-j) for i in args if i!=j]) \
849 for j in args])
851 def _eval_rewrite_as_Piecewise(self, *args, **kwargs):
852 return _minmax_as_Piecewise('<=', *args)
854 def _eval_is_positive(self):
855 return fuzzy_and(a.is_positive for a in self.args)
857 def _eval_is_nonnegative(self):
858 return fuzzy_and(a.is_nonnegative for a in self.args)
860 def _eval_is_negative(self):
861 return fuzzy_or(a.is_negative for a in self.args)
864class Rem(Function):
865 """Returns the remainder when ``p`` is divided by ``q`` where ``p`` is finite
866 and ``q`` is not equal to zero. The result, ``p - int(p/q)*q``, has the same sign
867 as the divisor.
869 Parameters
870 ==========
872 p : Expr
873 Dividend.
875 q : Expr
876 Divisor.
878 Notes
879 =====
881 ``Rem`` corresponds to the ``%`` operator in C.
883 Examples
884 ========
886 >>> from sympy.abc import x, y
887 >>> from sympy import Rem
888 >>> Rem(x**3, y)
889 Rem(x**3, y)
890 >>> Rem(x**3, y).subs({x: -5, y: 3})
891 -2
893 See Also
894 ========
896 Mod
897 """
898 kind = NumberKind
900 @classmethod
901 def eval(cls, p, q):
902 """Return the function remainder if both p, q are numbers and q is not
903 zero.
904 """
906 if q.is_zero:
907 raise ZeroDivisionError("Division by zero")
908 if p is S.NaN or q is S.NaN or p.is_finite is False or q.is_finite is False:
909 return S.NaN
910 if p is S.Zero or p in (q, -q) or (p.is_integer and q == 1):
911 return S.Zero
913 if q.is_Number:
914 if p.is_Number:
915 return p - Integer(p/q)*q