예제 #1
0
 def testReal(self):
     _test_group(
         MachineReal(1.17361),
         MachineReal(-1.42),
         MachineReal(42.846195714),
         MachineReal(42.846195714),
         MachineReal(42.846195713),
         Real("42.846195713", 18),
         Real("-1.42", 3),
     )
예제 #2
0
 def test_d(self):
     expr = Expression(
         "Plus", Symbol("x"), MachineReal(1.5), Integer(2), Symbol("x")
     )
     args = [CompileArg("System`x", real_type)]
     cfunc = _compile(expr, args)
     self.assertTypeEqual(cfunc(2.5), 8.5)
예제 #3
0
 def testInstances(self):
     # duplicate instantiations of same content (like Integer 5) to test for potential instantiation randomness.
     _test_group(
         list(
             map(lambda f: (f(), f()),
                 (lambda: Integer(5), lambda: Rational(5, 2),
                  lambda: MachineReal(5.12345678),
                  lambda: Complex(Integer(5), Integer(2)),
                  lambda: String('xy'), lambda: Symbol('xy')))))
예제 #4
0
    def get_constant(self, precision, evaluation, have_mpmath=False):
        try:
            d = get_precision(precision, evaluation)
        except PrecisionValueError:
            return

        sympy_fn = self.to_sympy()
        if d is None:
            result = self.get_mpmath_function() if have_mpmath else sympy_fn()
            return MachineReal(result)
        else:
            return PrecisionReal(sympy_fn.n(d))
예제 #5
0
    def apply_N(self, precision, evaluation):
        'N[E, precision_]'

        try:
            d = get_precision(precision, evaluation)
        except PrecisionValueError:
            return

        if d is None:
            return MachineReal(math.e)
        else:
            return PrecisionReal(sympy.E.n(d))
예제 #6
0
    def apply_N(self, precision, evaluation):
        "N[Pi, precision_]"

        try:
            d = get_precision(precision, evaluation)
        except PrecisionValueError:
            return

        if d is None:
            return MachineReal(math.pi)
        else:
            return PrecisionReal(sympy.pi.n(d))
예제 #7
0
    def apply_N(self, precision, evaluation):
        "N[Catalan, precision_]"

        try:
            d = get_precision(precision, evaluation)
        except PrecisionValueError:
            return

        if d is None:
            return MachineReal(mpmath.catalan)
        else:
            return PrecisionReal(sympy.Catalan.n(d))
예제 #8
0
파일: constants.py 프로젝트: srossd/Mathics
    def get_constant(self, precision, evaluation, preference=None):
        # first, determine the precision
        machine_d = int(0.30103 * machine_precision)
        d = None
        if precision:
            try:
                d = get_precision(precision, evaluation)
            except PrecisionValueError:
                pass

        if d is None:
            d = machine_d

        # If preference not especified, determine it
        # from the precision.
        if preference is None:
            if d <= machine_d:
                preference = "numpy"
            else:
                preference = "mpmath"
        # If preference is not valid, send a message and return.
        if not (preference in ("sympy", "numpy", "mpmath")):
            evaluation.message(
                f'{preference} not in ("sympy", "numpy", "mpmath")')
            return
        # Try to determine the numeric value
        value = None
        if preference == "mpmath" and not hasattr(self, "mpmath_name"):
            preference = "numpy"
        elif preference == "sympy" and not hasattr(self, "sympy_name"):
            preference = "numpy"

        if preference == "numpy" and not hasattr(self, "numpy_name"):
            if hasattr(self, "sympy_name"):
                preference = "sympy"
            elif hasattr(self, "mpmath_name"):
                preference = "mpmath"
            else:
                preference = ""
        if preference == "numpy":
            value = numpy_constant(self.numpy_name)
            if d == machine_d:
                return MachineReal(value)
        if preference == "sympy":
            value = sympy_constant(self.sympy_name, d + 2)
        if preference == "mpmath":
            value = mp_constant(self.mpmath_name, d * 2)
        if value:
            return PrecisionReal(sympy.Float(str(value), d))
        # If the value is not available, return none
        # and keep it unevaluated.
        return
예제 #9
0
파일: numbers.py 프로젝트: slel/Mathics
def get_precision(value, evaluation) -> typing.Optional[int]:
    if value.get_name() == 'System`MachinePrecision':
        return None
    else:
        from mathics.core.expression import Symbol, MachineReal
        dmin = _get_float_inf(Symbol('$MinPrecision'), evaluation)
        dmax = _get_float_inf(Symbol('$MaxPrecision'), evaluation)
        d = value.round_to_float(evaluation)
        assert dmin is not None and dmax is not None
        if d is None:
            evaluation.message('N', 'precbd', value)
        elif d < dmin:
            dmin = int(dmin)
            evaluation.message('N', 'precsm', value, MachineReal(dmin))
            return dmin
        elif d > dmax:
            dmax = int(dmax)
            evaluation.message('N', 'preclg', value, MachineReal(dmax))
            return dmax
        else:
            return d
        raise PrecisionValueError()
예제 #10
0
    def apply_N(self, precision, evaluation):
        "N[Degree, precision_]"
        try:
            d = get_precision(precision, evaluation)
        except PrecisionValueError:
            return

        # FIXME: There are all sorts of interactions between in the trig functions,
        # that are expected to work out right. Until we have convertion between
        # mpmath and sympy worked out so that values can be made the to the same
        # precision and compared. we have to not use mpmath right now.
        # return self.get_constant(precision, evaluation, preference="mpmath")

        if d is None:
            return MachineReal(math.pi / 180)
        else:
            return PrecisionReal((sympy.pi / 180).n(d))
예제 #11
0
파일: base.py 프로젝트: rjalif199/Mathics
    def get_constant(self, precision, evaluation, preference="mpmath"):
        try:
            d = get_precision(precision, evaluation)
        except PrecisionValueError:
            return

        mpmath_name = self.mpmath_name
        if d is None:
            return MachineReal(mp_fn(mpmath_name))
        elif preference == "mpmath":
            result = mp_fn(mpmath_name, d)
        else:
            sympy_fn = self.to_sympy()
            try:
                result = sympy_fn.n(d)
            except:
                from trepan.api import debug; debug()
                pass
        return PrecisionReal(result)
예제 #12
0
파일: base.py 프로젝트: rjalif199/Mathics
    def get_constant(self, precision, evaluation, preference="sympy"):
        try:
            d = get_precision(precision, evaluation)
        except PrecisionValueError:
            return

        sympy_fn = self.to_sympy()
        if d is None:
            if hasattr(self, "mpmath_name"):
                # Prefer mpmath when precision is not given.
                result = mp_fn(self.mpmath_name)
            else:
                result = sympy_fn()
            return MachineReal(result)

        if preference == "sympy":
            result = sympy_fn_n(d)
        elif hasattr(self, "mpmath_name"):
            result = mp_fn(self.mpmath_name, d)

        return PrecisionReal(result)
예제 #13
0
 def testReal(self):
     _test_group(MachineReal(1.17361), MachineReal(-1.42),
                 MachineReal(42.846195714), MachineReal(42.846195714),
                 MachineReal(42.846195713), Real('42.846195713', 18),
                 Real('-1.42', 3))
예제 #14
0
 def test_if_real_int(self):
     expr = Expression("If", Symbol("x"), MachineReal(3), Integer(2))
     args = [CompileArg("System`x", bool_type)]
     cfunc = _compile(expr, args)
     self.assertTypeEqual(cfunc(True), 3.0)
     self.assertTypeEqual(cfunc(False), 2.0)
예제 #15
0
 def test_pow_int_real(self):
     expr = Expression("Power", Symbol("x"), MachineReal(5.5))
     args = [CompileArg("System`x", int_type)]
     cfunc = _compile(expr, args)
     self.assertTypeEqual(cfunc(8), 8 ** 5.5)
예제 #16
0
 def test_pow_real_int(self):
     expr = Expression("Power", MachineReal(2.5), Symbol("x"))
     args = [CompileArg("System`x", int_type)]
     cfunc = _compile(expr, args)
     self.assertTypeEqual(cfunc(4), 2.5 ** 4)
예제 #17
0
파일: convert.py 프로젝트: yarwelp/Mathics
def from_sympy(expr):
    from mathics.builtin import sympy_to_mathics
    from mathics.core.expression import (Symbol, Integer, Rational, Real,
                                         Complex, String, Expression,
                                         MachineReal)
    from mathics.core.numbers import machine_precision

    from sympy.core import numbers, function, symbol

    if isinstance(expr, (tuple, list)):
        return Expression('List', *[from_sympy(item) for item in expr])
    if isinstance(expr, int):
        return Integer(expr)
    if isinstance(expr, float):
        return Real(expr)
    if isinstance(expr, complex):
        return Complex(Real(expr.real), Real(expr.imag))
    if isinstance(expr, six.string_types):
        return String(expr)
    if expr is None:
        return Symbol('Null')
    if isinstance(expr, sympy.Matrix):
        if len(expr.shape) == 2 and (expr.shape[1] == 1):
            # This is a vector (only one column)
            # Transpose and select first row to get result equivalent to Mathematica
            return Expression(
                'List', *[from_sympy(item) for item in expr.T.tolist()[0]])
        else:
            return Expression(
                'List',
                *[[from_sympy(item) for item in row] for row in expr.tolist()])
    if expr.is_Atom:
        name = None
        if expr.is_Symbol:
            name = six.text_type(expr)
            if isinstance(expr, symbol.Dummy):
                name = name + ('__Dummy_%d' % expr.dummy_index)
                return Symbol(name, sympy_dummy=expr)
            if is_Cn_expr(name):
                return Expression('C', int(name[1:]))
            if name.startswith(sympy_symbol_prefix):
                name = name[len(sympy_symbol_prefix):]
            if name.startswith(sympy_slot_prefix):
                index = name[len(sympy_slot_prefix):]
                return Expression('Slot', int(index))
        elif expr.is_NumberSymbol:
            name = six.text_type(expr)
        if name is not None:
            builtin = sympy_to_mathics.get(name)
            if builtin is not None:
                name = builtin.get_name()
            return Symbol(name)
        elif isinstance(expr, (numbers.Infinity, numbers.ComplexInfinity)):
            return Symbol(expr.__class__.__name__)
        elif isinstance(expr, numbers.NegativeInfinity):
            return Expression('Times', Integer(-1), Symbol('Infinity'))
        elif isinstance(expr, numbers.ImaginaryUnit):
            return Complex(Integer(0), Integer(1))
        elif isinstance(expr, numbers.Integer):
            return Integer(expr.p)
        elif isinstance(expr, numbers.Rational):
            if expr.q == 0:
                if expr.p > 0:
                    return Symbol('Infinity')
                elif expr.p < 0:
                    return Expression('Times', Integer(-1), Symbol('Infinity'))
                else:
                    assert expr.p == 0
                    return Symbol('Indeterminate')
            return Rational(expr.p, expr.q)
        elif isinstance(expr, numbers.Float):
            if expr._prec == machine_precision:
                return MachineReal(float(expr))
            return Real(expr)
        elif isinstance(expr, numbers.NaN):
            return Symbol('Indeterminate')
        elif isinstance(expr, function.FunctionClass):
            return Symbol(six.text_type(expr))
    elif expr.is_number and all([x.is_Number for x in expr.as_real_imag()]):
        # Hack to convert 3 * I to Complex[0, 3]
        return Complex(*[from_sympy(arg) for arg in expr.as_real_imag()])
    elif expr.is_Add:
        return Expression('Plus',
                          *sorted([from_sympy(arg) for arg in expr.args]))
    elif expr.is_Mul:
        return Expression('Times',
                          *sorted([from_sympy(arg) for arg in expr.args]))
    elif expr.is_Pow:
        return Expression('Power', *[from_sympy(arg) for arg in expr.args])
    elif expr.is_Equality:
        return Expression('Equal', *[from_sympy(arg) for arg in expr.args])

    elif isinstance(expr, SympyExpression):
        return expr.expr

    elif isinstance(expr, sympy.Piecewise):
        args = expr.args
        default = []
        if len(args) > 0:
            default_case, default_cond = args[-1]
            if default_cond == sympy.true:
                args = args[:-1]
                if isinstance(default_case,
                              sympy.Integer) and int(default_case) == 0:
                    pass  # ignore, as 0 default case is always implicit in Piecewise[]
                else:
                    default = [from_sympy(default_case)]
        return Expression(
            'Piecewise',
            Expression(
                'List', *[
                    Expression('List', from_sympy(case), from_sympy(cond))
                    for case, cond in args
                ]), *default)

    elif isinstance(expr, sympy.RootSum):
        return Expression('RootSum', from_sympy(expr.poly),
                          from_sympy(expr.fun))
    elif isinstance(expr, sympy.PurePoly):
        coeffs = expr.coeffs()
        monoms = expr.monoms()
        result = []
        for coeff, monom in zip(coeffs, monoms):
            factors = []
            if coeff != 1:
                factors.append(from_sympy(coeff))
            for index, exp in enumerate(monom):
                if exp != 0:
                    slot = Expression('Slot', index + 1)
                    if exp == 1:
                        factors.append(slot)
                    else:
                        factors.append(
                            Expression('Power', slot, from_sympy(exp)))
            if factors:
                result.append(Expression('Times', *factors))
            else:
                result.append(Integer(1))
        return Expression('Function', Expression('Plus', *result))
    elif isinstance(expr, sympy.Lambda):
        vars = [
            sympy.Symbol('%s%d' % (sympy_slot_prefix, index + 1))
            for index in range(len(expr.variables))
        ]
        return Expression('Function', from_sympy(expr(*vars)))

    elif expr.is_Function or isinstance(
            expr,
        (sympy.Integral, sympy.Derivative, sympy.Sum, sympy.Product)):
        if isinstance(expr, sympy.Integral):
            name = 'Integral'
        elif isinstance(expr, sympy.Derivative):
            name = 'Derivative'
        else:
            name = expr.func.__name__
            if is_Cn_expr(name):
                return Expression(Expression('C', int(name[1:])),
                                  *[from_sympy(arg) for arg in expr.args])
            if name.startswith(sympy_symbol_prefix):
                name = name[len(sympy_symbol_prefix):]
        args = [from_sympy(arg) for arg in expr.args]
        builtin = sympy_to_mathics.get(name)
        if builtin is not None:
            return builtin.from_sympy(name, args)
        return Expression(Symbol(name), *args)

    elif isinstance(expr, sympy.Tuple):
        return Expression('List', *[from_sympy(arg) for arg in expr.args])

    # elif isinstance(expr, sympy.Sum):
    #    return Expression('Sum', )

    elif isinstance(expr, sympy.LessThan):
        return Expression('LessEqual', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.StrictLessThan):
        return Expression('Less', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.GreaterThan):
        return Expression('GreaterEqual',
                          *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.StrictGreaterThan):
        return Expression('Greater', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.Unequality):
        return Expression('Unequal', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.Equality):
        return Expression('Equal', *[from_sympy(arg) for arg in expr.args])
    elif expr is sympy.true:
        return Symbol('True')
    elif expr is sympy.false:
        return Symbol('False')
    else:
        raise ValueError("Unknown SymPy expression: %s" % expr)
예제 #18
0
 def evaluate(self, evaluation):
     return MachineReal(machine_epsilon)
예제 #19
0
 def test_d(self):
     expr = Expression('Plus', Symbol('x'), MachineReal(1.5), Integer(2),
                       Symbol('x'))
     args = [CompileArg('System`x', real_type)]
     cfunc = _compile(expr, args)
     self.assertTypeEqual(cfunc(2.5), 8.5)
예제 #20
0
 def test_if_int_real(self):
     expr = Expression('If', Symbol('x'), Integer(2), MachineReal(3))
     args = [CompileArg('System`x', bool_type)]
     cfunc = _compile(expr, args)
     self.assertTypeEqual(cfunc(True), 2.0)
     self.assertTypeEqual(cfunc(False), 3.0)
예제 #21
0
def from_sympy(expr):
    from mathics.builtin import sympy_to_mathics
    from mathics.core.expression import (Symbol, Integer, Rational, Real,
                                         Complex, String, Expression,
                                         MachineReal)
    from mathics.core.numbers import machine_precision

    if isinstance(expr, (tuple, list)):
        return Expression('List', *[from_sympy(item) for item in expr])
    if isinstance(expr, int):
        return Integer(expr)
    if isinstance(expr, float):
        return Real(expr)
    if isinstance(expr, complex):
        return Complex(Real(expr.real), Real(expr.imag))
    if isinstance(expr, str):
        return String(expr)
    if expr is None:
        return Symbol('Null')
    if isinstance(expr, sympy.Matrix) or isinstance(expr,
                                                    sympy.ImmutableMatrix):
        if len(expr.shape) == 2 and (expr.shape[1] == 1):
            # This is a vector (only one column)
            # Transpose and select first row to get result equivalent to Mathematica
            return Expression(
                'List', *[from_sympy(item) for item in expr.T.tolist()[0]])
        else:
            return Expression(
                'List',
                *[[from_sympy(item) for item in row] for row in expr.tolist()])
    if isinstance(expr, sympy.MatPow):
        return Expression('MatrixPower', from_sympy(expr.base),
                          from_sympy(expr.exp))
    if expr.is_Atom:
        name = None
        if expr.is_Symbol:
            name = str(expr)
            if isinstance(expr, sympy.Dummy):
                name = name + ('__Dummy_%d' % expr.dummy_index)
                return Symbol(name, sympy_dummy=expr)
            if is_Cn_expr(name):
                return Expression('C', int(name[1:]))
            if name.startswith(sympy_symbol_prefix):
                name = name[len(sympy_symbol_prefix):]
            if name.startswith(sympy_slot_prefix):
                index = name[len(sympy_slot_prefix):]
                return Expression('Slot', int(index))
        elif expr.is_NumberSymbol:
            name = str(expr)
        if name is not None:
            builtin = sympy_to_mathics.get(name)
            if builtin is not None:
                name = builtin.get_name()
            return Symbol(name)
        elif isinstance(
                expr,
            (sympy.core.numbers.Infinity, sympy.core.numbers.ComplexInfinity)):
            return Symbol(expr.__class__.__name__)
        elif isinstance(expr, sympy.core.numbers.NegativeInfinity):
            return Expression('Times', Integer(-1), Symbol('Infinity'))
        elif isinstance(expr, sympy.core.numbers.ImaginaryUnit):
            return Complex(Integer(0), Integer(1))
        elif isinstance(expr, sympy.Integer):
            return Integer(int(expr))
        elif isinstance(expr, sympy.Rational):
            numerator, denominator = map(int, expr.as_numer_denom())
            if denominator == 0:
                if numerator > 0:
                    return Symbol('Infinity')
                elif numerator < 0:
                    return Expression('Times', Integer(-1), Symbol('Infinity'))
                else:
                    assert numerator == 0
                    return Symbol('Indeterminate')
            return Rational(numerator, denominator)
        elif isinstance(expr, sympy.Float):
            if expr._prec == machine_precision:
                return MachineReal(float(expr))
            return Real(expr)
        elif isinstance(expr, sympy.core.numbers.NaN):
            return Symbol('Indeterminate')
        elif isinstance(expr, sympy.core.function.FunctionClass):
            return Symbol(str(expr))
        elif expr is sympy.true:
            return Symbol('True')
        elif expr is sympy.false:
            return Symbol('False')

    elif expr.is_number and all([x.is_Number for x in expr.as_real_imag()]):
        # Hack to convert 3 * I to Complex[0, 3]
        return Complex(*[from_sympy(arg) for arg in expr.as_real_imag()])
    elif expr.is_Add:
        return Expression('Plus',
                          *sorted([from_sympy(arg) for arg in expr.args]))
    elif expr.is_Mul:
        return Expression('Times',
                          *sorted([from_sympy(arg) for arg in expr.args]))
    elif expr.is_Pow:
        return Expression('Power', *[from_sympy(arg) for arg in expr.args])
    elif expr.is_Equality:
        return Expression('Equal', *[from_sympy(arg) for arg in expr.args])

    elif isinstance(expr, SympyExpression):
        return expr.expr

    elif isinstance(expr, sympy.Piecewise):
        args = expr.args
        return Expression(
            'Piecewise',
            Expression(
                'List', *[
                    Expression('List', from_sympy(case), from_sympy(cond))
                    for case, cond in args
                ]))

    elif isinstance(expr, SympyPrime):
        return Expression('Prime', from_sympy(expr.args[0]))
    elif isinstance(expr, sympy.RootSum):
        return Expression('RootSum', from_sympy(expr.poly),
                          from_sympy(expr.fun))
    elif isinstance(expr, sympy.PurePoly):
        coeffs = expr.coeffs()
        monoms = expr.monoms()
        result = []
        for coeff, monom in zip(coeffs, monoms):
            factors = []
            if coeff != 1:
                factors.append(from_sympy(coeff))
            for index, exp in enumerate(monom):
                if exp != 0:
                    slot = Expression('Slot', index + 1)
                    if exp == 1:
                        factors.append(slot)
                    else:
                        factors.append(
                            Expression('Power', slot, from_sympy(exp)))
            if factors:
                result.append(Expression('Times', *factors))
            else:
                result.append(Integer(1))
        return Expression('Function', Expression('Plus', *result))
    elif isinstance(expr, sympy.CRootOf):
        try:
            e, i = expr.args
        except ValueError:
            return Expression('Null')

        try:
            e = sympy.PurePoly(e)
        except:
            pass

        return Expression('Root', from_sympy(e), i + 1)
    elif isinstance(expr, sympy.Lambda):
        vars = [
            sympy.Symbol('%s%d' % (sympy_slot_prefix, index + 1))
            for index in range(len(expr.variables))
        ]
        return Expression('Function', from_sympy(expr(*vars)))

    elif expr.is_Function or isinstance(
            expr,
        (sympy.Integral, sympy.Derivative, sympy.Sum, sympy.Product)):
        if isinstance(expr, sympy.Integral):
            name = 'Integral'
        elif isinstance(expr, sympy.Derivative):
            name = 'Derivative'
            margs = []
            for arg in expr.args:
                # parse (x, 1) ==> just x for test_conversion
                # IMHO this should be removed in future versions
                if isinstance(arg, sympy.Tuple):
                    if arg[1] == 1:
                        margs.append(from_sympy(arg[0]))
                    else:
                        margs.append(from_sympy(arg))
                else:
                    margs.append(from_sympy(arg))
            builtin = sympy_to_mathics.get(name)
            return builtin.from_sympy(name, margs)

        elif isinstance(expr, sympy.sign):
            name = 'Sign'
        else:
            name = expr.func.__name__
            if is_Cn_expr(name):
                return Expression(Expression('C', int(name[1:])),
                                  *[from_sympy(arg) for arg in expr.args])
            if name.startswith(sympy_symbol_prefix):
                name = name[len(sympy_symbol_prefix):]
        args = [from_sympy(arg) for arg in expr.args]
        builtin = sympy_to_mathics.get(name)
        if builtin is not None:
            return builtin.from_sympy(name, args)
        return Expression(Symbol(name), *args)

    elif isinstance(expr, sympy.Tuple):
        return Expression('List', *[from_sympy(arg) for arg in expr.args])

    # elif isinstance(expr, sympy.Sum):
    #    return Expression('Sum', )

    elif isinstance(expr, sympy.LessThan):
        return Expression('LessEqual', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.StrictLessThan):
        return Expression('Less', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.GreaterThan):
        return Expression('GreaterEqual',
                          *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.StrictGreaterThan):
        return Expression('Greater', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.Unequality):
        return Expression('Unequal', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.Equality):
        return Expression('Equal', *[from_sympy(arg) for arg in expr.args])

    elif isinstance(expr, sympy.O):
        if expr.args[0].func == sympy.core.power.Pow:
            [var, power] = [from_sympy(arg) for arg in expr.args[0].args]
            o = Expression('O', var)
            return Expression('Power', o, power)
        else:
            return Expression('O', from_sympy(expr.args[0]))
    else:
        raise ValueError(
            "Unknown SymPy expression: {} (instance of {})".format(
                expr, str(expr.__class__)))
예제 #22
0
 def c(i, r):
     return Complex(MachineReal(i), MachineReal(i))