def _eval_imageset(self, f):
        from sympy.functions.elementary.miscellaneous import Min, Max
        from sympy.solvers.solveset import solveset
        from sympy.core.function import diff, Lambda
        from sympy.series import limit
        from sympy.calculus.singularities import singularities
        # TODO: handle functions with infinitely many solutions (eg, sin, tan)
        # TODO: handle multivariate functions

        expr = f.expr
        if len(expr.free_symbols) > 1 or len(f.variables) != 1:
            return
        var = f.variables[0]

        if expr.is_Piecewise:
            result = S.EmptySet
            domain_set = self
            for (p_expr, p_cond) in expr.args:
                if p_cond is true:
                    intrvl = domain_set
                else:
                    intrvl = p_cond.as_set()
                    intrvl = Intersection(domain_set, intrvl)

                if p_expr.is_Number:
                    image = FiniteSet(p_expr)
                else:
                    image = imageset(Lambda(var, p_expr), intrvl)
                result = Union(result, image)

                # remove the part which has been `imaged`
                domain_set = Complement(domain_set, intrvl)
                if domain_set.is_EmptySet:
                    break
            return result

        if not self.start.is_comparable or not self.end.is_comparable:
            return

        try:
            sing = [x for x in singularities(expr, var)
                if x.is_real and x in self]
        except __HOLE__:
            return

        if self.left_open:
            _start = limit(expr, var, self.start, dir="+")
        elif self.start not in sing:
            _start = f(self.start)
        if self.right_open:
            _end = limit(expr, var, self.end, dir="-")
        elif self.end not in sing:
            _end = f(self.end)

        if len(sing) == 0:
            solns = list(solveset(diff(expr, var), var))

            extr = [_start, _end] + [f(x) for x in solns
                                     if x.is_real and x in self]
            start, end = Min(*extr), Max(*extr)

            left_open, right_open = False, False
            if _start <= _end:
                # the minimum or maximum value can occur simultaneously
                # on both the edge of the interval and in some interior
                # point
                if start == _start and start not in solns:
                    left_open = self.left_open
                if end == _end and end not in solns:
                    right_open = self.right_open
            else:
                if start == _end and start not in solns:
                    left_open = self.right_open
                if end == _start and end not in solns:
                    right_open = self.left_open

            return Interval(start, end, left_open, right_open)
        else:
            return imageset(f, Interval(self.start, sing[0],
                                        self.left_open, True)) + \
                Union(*[imageset(f, Interval(sing[i], sing[i + 1], True, True))
                        for i in range(0, len(sing) - 1)]) + \
                imageset(f, Interval(sing[-1], self.end, True, self.right_open))
dataset/ETHPy150Open sympy/sympy/sympy/sets/sets.py/Interval._eval_imageset