Exemplo n.º 1
0
    def _evalf_(self, x, **kwds):
        """
        TESTS:

        Check that :trac:`16587` is fixed::

            sage: M = sgn(3/2, hold=True); M
            sgn(3/2)
            sage: M.n()
            1
            sage: h(x) = sgn(x)
            sage: h(pi).numerical_approx()
            1.00000000000000
        """
        if hasattr(x,'sign'): # First check if x has a sign method
            return x.sign()
        if hasattr(x,'sgn'): # or a sgn method
            return x.sgn()
        approx_x = ComplexIntervalField()(x)
        if bool(approx_x.imag() == 0):      # x is real
            if bool(approx_x.real() == 0):  # x is zero
                return ZZ(0)
            # Now we have a non-zero real
            if bool((approx_x**(0.5)).imag() == 0): # Check: x > 0
                return ZZ(1)
            else:
                return ZZ(-1)
        raise ValueError("Numeric evaluation of symbolic expression")
Exemplo n.º 2
0
    def _evalf_(self, x, **kwds):
        """
        TESTS:

        Check that :trac:`16587` is fixed::

            sage: M = sgn(3/2, hold=True); M
            sgn(3/2)
            sage: M.n()
            1
            sage: h(x) = sgn(x)
            sage: h(pi).numerical_approx()
            1.00000000000000
        """
        if hasattr(x, 'sign'):  # First check if x has a sign method
            return x.sign()
        if hasattr(x, 'sgn'):  # or a sgn method
            return x.sgn()
        approx_x = ComplexIntervalField()(x)
        if bool(approx_x.imag() == 0):  # x is real
            if bool(approx_x.real() == 0):  # x is zero
                return ZZ(0)
            # Now we have a non-zero real
            if bool((approx_x**(0.5)).imag() == 0):  # Check: x > 0
                return ZZ(1)
            else:
                return ZZ(-1)
        raise ValueError("Numeric evaluation of symbolic expression")
Exemplo n.º 3
0
    def _eval_(self, x):
        """
        INPUT:
        
        -  ``x`` - a real number or a symbolic expression
        
        EXAMPLES::

            sage: dirac_delta(1)
            0
            sage: dirac_delta(0)
            dirac_delta(0)
            sage: dirac_delta(x)
            dirac_delta(x)
            sage: dirac_delta(exp(-10000000000000000000))
            0

        Evaluation test::
            
            sage: dirac_delta(x).subs(x=1)
            0
        """
        try:
            approx_x = ComplexIntervalField()(x)
            if bool(approx_x.imag() == 0):  # x is real
                if bool(approx_x.real() == 0):  # x is zero
                    return None
                else:
                    return 0
        except StandardError:  # x is symbolic
            pass
        return None
Exemplo n.º 4
0
    def _eval_(self, x):
        """
        INPUT:

        -  ``x`` - a real number or a symbolic expression

        EXAMPLES::

            sage: dirac_delta(1)
            0
            sage: dirac_delta(0)
            dirac_delta(0)
            sage: dirac_delta(x)
            dirac_delta(x)
            sage: dirac_delta(exp(-10000000000000000000))
            0

        Evaluation test::

            sage: dirac_delta(x).subs(x=1)
            0
        """
        try:
            approx_x = ComplexIntervalField()(x)
            if bool(approx_x.imag() == 0):      # x is real
                if bool(approx_x.real() == 0):  # x is zero
                    return None
                else:
                    return 0
        except Exception:                     # x is symbolic
            pass
        return None
Exemplo n.º 5
0
def _is_numerically_zero_CIF(x):
    from sage.rings.all import ComplexIntervalField
    try:
        approx_x = ComplexIntervalField()(x)
        if bool(approx_x.imag() == 0) and bool(approx_x.real() == 0):
            return True
    except:
        return False
Exemplo n.º 6
0
    def _eval_(self, x):
        """
        
        EXAMPLES::

            sage: sgn(-1)
            -1
            sage: sgn(1)
            1
            sage: sgn(0)
            0
            sage: sgn(x)
            sgn(x)
            sage: sgn(-exp(-10000000000000000000))
            -1

        Evaluation test::
            
            sage: sgn(x).subs(x=1)
            1
            sage: sgn(x).subs(x=0)
            0
            sage: sgn(x).subs(x=-1)
            -1

        More tests::

            sage: sign(RR(2))
            1
            sage: sign(RDF(2))
            1
            sage: sign(AA(-2))
            -1
            sage: sign(AA(0))
            0
        """
        if hasattr(x, 'sign'):  # First check if x has a sign method
            return x.sign()
        if hasattr(x, 'sgn'):  # or a sgn method
            return x.sgn()
        try:
            approx_x = ComplexIntervalField()(x)
            if bool(approx_x.imag() == 0):  # x is real
                if bool(approx_x.real() == 0):  # x is zero
                    return ZZ(0)
                # Now we have a non-zero real
                if bool((approx_x**(0.5)).imag() == 0):  # Check: x > 0
                    return ZZ(1)
                else:
                    return ZZ(-1)
        except StandardError:  # x is symbolic
            pass
        return None
Exemplo n.º 7
0
    def _eval_(self, x):
        """

        EXAMPLES::

            sage: sgn(-1)
            -1
            sage: sgn(1)
            1
            sage: sgn(0)
            0
            sage: sgn(x)
            sgn(x)
            sage: sgn(-exp(-10000000000000000000))
            -1

        Evaluation test::

            sage: sgn(x).subs(x=1)
            1
            sage: sgn(x).subs(x=0)
            0
            sage: sgn(x).subs(x=-1)
            -1

        More tests::

            sage: sign(RR(2))
            1
            sage: sign(RDF(2))
            1
            sage: sign(AA(-2))
            -1
            sage: sign(AA(0))
            0
        """
        if hasattr(x,'sign'): # First check if x has a sign method
            return x.sign()
        if hasattr(x,'sgn'): # or a sgn method
            return x.sgn()
        try:
            approx_x = ComplexIntervalField()(x)
            if bool(approx_x.imag() == 0):      # x is real
                if bool(approx_x.real() == 0):  # x is zero
                    return ZZ(0)
                # Now we have a non-zero real
                if bool((approx_x**(0.5)).imag() == 0): # Check: x > 0
                    return ZZ(1)
                else:
                    return ZZ(-1)
        except Exception:                     # x is symbolic
            pass
        return None
Exemplo n.º 8
0
    def _eval_(self, x):
        """
        INPUT:

        -  ``x`` - a real number or a symbolic expression

        EXAMPLES::

            sage: heaviside(-1/2)
            0
            sage: heaviside(1)
            1
            sage: heaviside(0)
            heaviside(0)
            sage: heaviside(x)
            heaviside(x)
            sage: heaviside(exp(-1000000000000000000000))
            1

        Evaluation test::

            sage: heaviside(x).subs(x=1)
            1
            sage: heaviside(x).subs(x=-1)
            0

        ::

            sage: ex = heaviside(x)+1
            sage: t = loads(dumps(ex)); t
            heaviside(x) + 1
            sage: bool(t == ex)
            True
            sage: t.subs(x=1)
            2
        """
        try:
            approx_x = ComplexIntervalField()(x)
            if bool(approx_x.imag() == 0):      # x is real
                if bool(approx_x.real() == 0):  # x is zero
                    return None
                # Now we have a non-zero real
                if bool((approx_x**(0.5)).imag() == 0): # Check: x > 0
                    return 1
                else:
                    return 0
        except Exception:                     # x is symbolic
            pass
        return None
Exemplo n.º 9
0
    def _eval_(self, x):
        """
        INPUT:
        
        -  ``x`` - a real number or a symbolic expression
        
        EXAMPLES::

            sage: heaviside(-1/2)
            0
            sage: heaviside(1)
            1
            sage: heaviside(0)
            heaviside(0)
            sage: heaviside(x)
            heaviside(x)
            sage: heaviside(exp(-1000000000000000000000))
            1

        Evaluation test::
            
            sage: heaviside(x).subs(x=1)
            1
            sage: heaviside(x).subs(x=-1)
            0

        ::

            sage: ex = heaviside(x)+1
            sage: t = loads(dumps(ex)); t
            heaviside(x) + 1
            sage: bool(t == ex)
            True
            sage: t.subs(x=1)
            2
        """
        try:
            approx_x = ComplexIntervalField()(x)
            if bool(approx_x.imag() == 0):  # x is real
                if bool(approx_x.real() == 0):  # x is zero
                    return None
                # Now we have a non-zero real
                if bool((approx_x**(0.5)).imag() == 0):  # Check: x > 0
                    return 1
                else:
                    return 0
        except StandardError:  # x is symbolic
            pass
        return None
Exemplo n.º 10
0
    def _evalf_(self, x, **kwds):
        """
        TESTS::

            sage: h(x) = dirac_delta(x)
            sage: h(pi).numerical_approx()
            0.000000000000000
        """
        approx_x = ComplexIntervalField()(x)
        if bool(approx_x.imag() == 0):      # x is real
            if bool(approx_x.real() == 0):  # x is zero
                return None
            else:
                return 0
        raise ValueError("Numeric evaluation of symbolic expression")
Exemplo n.º 11
0
    def _evalf_(self, x, **kwds):
        """
        TESTS::

            sage: h(x) = dirac_delta(x)
            sage: h(pi).numerical_approx()
            0.000000000000000
        """
        approx_x = ComplexIntervalField()(x)
        if bool(approx_x.imag() == 0):  # x is real
            if bool(approx_x.real() == 0):  # x is zero
                return None
            else:
                return 0
        raise ValueError("Numeric evaluation of symbolic expression")
Exemplo n.º 12
0
    def _evalf_(self, x, **kwds):
        """
        TESTS::

            sage: h(x) = unit_step(x)
            sage: h(pi).numerical_approx()
            1.00000000000000
        """
        approx_x = ComplexIntervalField()(x)
        if bool(approx_x.imag() == 0):      # x is real
            if bool(approx_x.real() == 0):  # x is zero
                return 1
            # Now we have a non-zero real
            if bool((approx_x**(0.5)).imag() == 0): # Check: x > 0
                return 1
            else:
                return 0
        raise ValueError("Numeric evaluation of symbolic expression")
Exemplo n.º 13
0
    def _evalf_(self, m, n, **kwds):
        """
        TESTS::

            sage: h(x) = kronecker_delta(3,x)
            sage: h(pi).numerical_approx()
            0.000000000000000
        """
        if bool(repr(m) > repr(n)):
            return kronecker_delta(n, m)
        x = m - n
        approx_x = ComplexIntervalField()(x)
        if approx_x.imag() == 0:      # x is real
            if approx_x.real() == 0:  # x is zero
                return 1
            else:
                return 0
        return 0            # x is complex
Exemplo n.º 14
0
    def _evalf_(self, x, **kwds):
        """
        TESTS::

            sage: h(x) = unit_step(x)
            sage: h(pi).numerical_approx()
            1.00000000000000
        """
        approx_x = ComplexIntervalField()(x)
        if bool(approx_x.imag() == 0):  # x is real
            if bool(approx_x.real() == 0):  # x is zero
                return 1
            # Now we have a non-zero real
            if bool((approx_x**(0.5)).imag() == 0):  # Check: x > 0
                return 1
            else:
                return 0
        raise ValueError("Numeric evaluation of symbolic expression")
Exemplo n.º 15
0
    def _eval_(self, m, n):
        """
        The Kronecker delta function.

        EXAMPLES::

            sage: kronecker_delta(1,2)
            0
            sage: kronecker_delta(1,1)
            1

        Kronecker delta is a symmetric function. We keep arguments sorted to
        ensure that k_d(m, n) - k_d(n, m) cancels automatically::

            sage: x,y=var('x,y')
            sage: kronecker_delta(x, y)
            kronecker_delta(x, y)
            sage: kronecker_delta(y, x)
            kronecker_delta(x, y)
            sage: kronecker_delta(x,2*x)
            kronecker_delta(2*x, x)

        Evaluation test::

            sage: kronecker_delta(1,x).subs(x=1)
            1
        """
        if bool(repr(m) > repr(n)):
            return kronecker_delta(n, m)

        x = m - n
        try:
            approx_x = ComplexIntervalField()(x)
            if bool(approx_x.imag() == 0):      # x is real
                if bool(approx_x.real() == 0):  # x is zero
                    return 1
                else:
                    return 0
            else:
                return 0            # x is complex
        except Exception:                     # x is symbolic
            pass
        return None
Exemplo n.º 16
0
    def _eval_(self, m, n):
        """
        The Kronecker delta function.

        EXAMPLES::

            sage: kronecker_delta(1,2)
            0
            sage: kronecker_delta(1,1)
            1

        Kronecker delta is a symmetric function. We keep arguments sorted to
        ensure that (k_d(m, n) - k_d(n, m) cancels automatically::

            sage: x,y=var('x,y')
            sage: kronecker_delta(x, y)
            kronecker_delta(x, y)
            sage: kronecker_delta(y, x)
            kronecker_delta(x, y)
            sage: kronecker_delta(x,2*x)
            kronecker_delta(2*x, x)

        Evaluation test::
            
            sage: kronecker_delta(1,x).subs(x=1)
            1
        """
        if bool(repr(m) > repr(n)):
            return kronecker_delta(n, m)

        x = m - n
        try:
            approx_x = ComplexIntervalField()(x)
            if bool(approx_x.imag() == 0):  # x is real
                if bool(approx_x.real() == 0):  # x is zero
                    return 1
                else:
                    return 0
            else:
                return 0  # x is complex
        except StandardError:  # x is symbolic
            pass
        return None
Exemplo n.º 17
0
    def _evalf_(self, m, n, **kwds):
        """
        TESTS::

            sage: h(x) = kronecker_delta(3,x)
            sage: h(pi).numerical_approx()
            0.000000000000000
        """
        if bool(repr(m) > repr(n)):
            return kronecker_delta(n, m)

        x = m - n
        approx_x = ComplexIntervalField()(x)
        if bool(approx_x.imag() == 0):  # x is real
            if bool(approx_x.real() == 0):  # x is zero
                return 1
            else:
                return 0
        else:
            return 0  # x is complex
        raise ValueError("Numeric evaluation of symbolic expression")
Exemplo n.º 18
0
    def _evalf_(self, m, n, **kwds):
        """
        TESTS::

            sage: h(x) = kronecker_delta(3,x)
            sage: h(pi).numerical_approx()
            0.000000000000000
        """
        if bool(repr(m) > repr(n)):
            return kronecker_delta(n, m)

        x = m - n
        approx_x = ComplexIntervalField()(x)
        if bool(approx_x.imag() == 0):      # x is real
            if bool(approx_x.real() == 0):  # x is zero
                return 1
            else:
                return 0
        else:
            return 0            # x is complex
        raise ValueError("Numeric evaluation of symbolic expression")
Exemplo n.º 19
0
    def _eval_(self, x):
        """
        INPUT:

        -  ``x`` - a real number or a symbolic expression

        EXAMPLES::

            sage: unit_step(-1)
            0
            sage: unit_step(1)
            1
            sage: unit_step(0)
            1
            sage: unit_step(x)
            unit_step(x)
            sage: unit_step(-exp(-10000000000000000000))
            0

        Evaluation test::

            sage: unit_step(x).subs(x=1)
            1
            sage: unit_step(x).subs(x=0)
            1
        """
        try:
            approx_x = ComplexIntervalField()(x)
            if bool(approx_x.imag() == 0):      # x is real
                if bool(approx_x.real() == 0):  # x is zero
                    return 1
                # Now we have a non-zero real
                if bool((approx_x**(0.5)).imag() == 0): # Check: x > 0
                    return 1
                else:
                    return 0
        except Exception:                     # x is symbolic
            pass
        return None
Exemplo n.º 20
0
    def _eval_(self, x):
        """
        INPUT:
        
        -  ``x`` - a real number or a symbolic expression
        
        EXAMPLES::

            sage: unit_step(-1)
            0
            sage: unit_step(1)
            1
            sage: unit_step(0)
            1
            sage: unit_step(x)
            unit_step(x)
            sage: unit_step(-exp(-10000000000000000000))
            0

        Evaluation test::
            
            sage: unit_step(x).subs(x=1)
            1
            sage: unit_step(x).subs(x=0)
            1
        """
        try:
            approx_x = ComplexIntervalField()(x)
            if bool(approx_x.imag() == 0):  # x is real
                if bool(approx_x.real() == 0):  # x is zero
                    return 1
                # Now we have a non-zero real
                if bool((approx_x**(0.5)).imag() == 0):  # Check: x > 0
                    return 1
                else:
                    return 0
        except StandardError:  # x is symbolic
            pass
        return None
Exemplo n.º 21
0
def dimension__vector_valued(k, L, conjugate=False):
    r"""
    Compute the dimension of the space of weight `k` vector valued modular forms
    for the Weil representation (or its conjugate) attached to the lattice `L`.
    
    See [Borcherds, Borcherds - Reflection groups of Lorentzian lattices] for a proof
    of the formula that we use here.
    
    INPUT:
    
    - `k` -- A half-integer.
    
    - ``L`` -- An quadratic form.
    
    - ``conjugate`` -- A boolean; If ``True``, then compute the dimension for
                       the conjugated Weil representation.
    
    OUTPUT:
        An integer.

    TESTS::

        sage: dimension__vector_valued(3, QuadraticForm(-matrix(2, [2, 1, 1, 2])))
        1
        sage: dimension__vector_valued(3, QuadraticForm(-matrix(2, [2, 0, 0, 2])))
        1
        sage: dimension__vector_valued(3, QuadraticForm(-matrix(2, [2, 0, 0, 4])))
        1
    """
    if 2 * k not in ZZ:
        raise ValueError("Weight must be half-integral")
    if k <= 0:
        return 0
    if k < 2:
        raise NotImplementedError("Weight <2 is not implemented.")

    if L.matrix().rank() != L.matrix().nrows():
        raise ValueError(
            "The lattice (={0}) must be non-degenerate.".format(L))

    L_dimension = L.matrix().nrows()
    if L_dimension % 2 != ZZ(2 * k) % 2:
        return 0

    plus_basis = ZZ(L_dimension + 2 * k) % 4 == 0

    ## The bilinear and the quadratic form attached to L
    quadratic = lambda x: L(x) // 2
    bilinear = lambda x, y: L(x + y) - L(x) - L(y)

    ## A dual basis for L
    (elementary_divisors, dual_basis_pre, _) = L.matrix().smith_form()
    elementary_divisors = elementary_divisors.diagonal()
    dual_basis = map(operator.div, list(dual_basis_pre), elementary_divisors)

    L_level = ZZ(lcm([b.denominator() for b in dual_basis]))

    (elementary_divisors, _, discriminant_basis_pre) = (
        L_level * matrix(dual_basis)).change_ring(ZZ).smith_form()
    elementary_divisors = filter(lambda d: d not in ZZ,
                                 (elementary_divisors / L_level).diagonal())
    elementary_divisors_inv = map(ZZ, [ed**-1 for ed in elementary_divisors])
    discriminant_basis = matrix(
        map(operator.mul,
            discriminant_basis_pre.inverse().rows()[:len(elementary_divisors)],
            elementary_divisors)).transpose()
    ## This is a form over QQ, so that we cannot use an instance of QuadraticForm
    discriminant_form = discriminant_basis.transpose() * L.matrix(
    ) * discriminant_basis

    if conjugate:
        discriminant_form = -discriminant_form

    if prod(elementary_divisors_inv) > 100:
        disc_den = discriminant_form.denominator()
        disc_bilinear_pre = \
            cython_lambda( ', '.join(   ['int a{0}'.format(i) for i in range(discriminant_form.nrows())]
                                        + ['int b{0}'.format(i) for i in range(discriminant_form.nrows())] ),
                           ' + '.join('{0} * a{1} * b{2}'.format(disc_den * discriminant_form[i,j], i, j)
                                      for i in range(discriminant_form.nrows())
                                      for j in range(discriminant_form.nrows())) )
        disc_bilinear = lambda *a: disc_bilinear_pre(*a) / disc_den
    else:
        disc_bilinear = lambda *xy: vector(ZZ, xy[:discriminant_form.nrows(
        )]) * discriminant_form * vector(ZZ, xy[discriminant_form.nrows():])

    disc_quadratic = lambda *a: disc_bilinear(*(2 * a)) / 2

    ## red gives a normal form for elements in the discriminant group
    red = lambda x: map(operator.mod, x, elementary_divisors_inv)

    def is_singl(x):
        y = red(map(operator.neg, x))
        for (e, f) in zip(x, y):
            if e < f:
                return -1
            elif e > f:
                return 1
        return 0

    ## singls and pairs are elements of the discriminant group that are, respectively,
    ## fixed and not fixed by negation.
    singls = list()
    pairs = list()
    for x in mrange(elementary_divisors_inv):
        si = is_singl(x)
        if si == 0:
            singls.append(x)
        elif si == 1:
            pairs.append(x)

    if plus_basis:
        subspace_dimension = len(singls + pairs)
    else:
        subspace_dimension = len(pairs)

    ## 200 bits are, by far, sufficient to distinguish 12-th roots of unity
    ## by increasing the precision by 4 for each additional dimension, we
    ## compensate, by far, the errors introduced by the QR decomposition,
    ## which are of the size of (absolute error) * dimension
    CC = ComplexIntervalField(200 + subspace_dimension * 4)

    zeta_order = ZZ(
        lcm([8, 12] + map(lambda ed: 2 * ed, elementary_divisors_inv)))

    zeta = CC(exp(2 * pi * I / zeta_order))
    sqrt2 = CC(sqrt(2))
    drt = CC(sqrt(L.det()))

    Tmat = diagonal_matrix(CC, [
        zeta**(zeta_order * disc_quadratic(*a))
        for a in (singls + pairs if plus_basis else pairs)
    ])
    if plus_basis:
        Smat = zeta**(zeta_order / 8 * L_dimension) / drt  \
               * matrix( CC, [  [zeta**(-zeta_order * disc_bilinear(*(gamma + delta))) for delta in singls]
                              + [sqrt2 * zeta**(-zeta_order * disc_bilinear(*(gamma + delta))) for delta in pairs]
                              for gamma in singls] \
                           + [  [sqrt2 * zeta**(-zeta_order * disc_bilinear(*(gamma + delta))) for delta in singls]
                              + [zeta**(-zeta_order * disc_bilinear(*(gamma + delta))) + zeta**(-zeta_order * disc_bilinear(*(gamma + map(operator.neg, delta)))) for delta in pairs]
                              for gamma in pairs] )
    else:
        Smat = zeta**(zeta_order / 8 * L_dimension) / drt  \
               * matrix( CC, [  [zeta**(-zeta_order * disc_bilinear(*(gamma + delta))) - zeta**(-zeta_order * disc_bilinear(*(gamma + map(operator.neg,delta))))  for delta in pairs]
                               for gamma in pairs ] )
    STmat = Smat * Tmat

    ## This function overestimates the number of eigenvalues, if it is not correct
    def eigenvalue_multiplicity(mat, ev):
        mat = matrix(CC, mat - ev * identity_matrix(subspace_dimension))
        return len(
            filter(lambda row: all(e.contains_zero() for e in row),
                   _qr(mat).rows()))

    rti = CC(exp(2 * pi * I / 8))
    S_ev_multiplicity = [
        eigenvalue_multiplicity(Smat, rti**n) for n in range(8)
    ]
    ## Together with the fact that eigenvalue_multiplicity overestimates the multiplicities
    ## this asserts that the computed multiplicities are correct
    assert sum(S_ev_multiplicity) == subspace_dimension

    rho = CC(exp(2 * pi * I / 12))
    ST_ev_multiplicity = [
        eigenvalue_multiplicity(STmat, rho**n) for n in range(12)
    ]
    ## Together with the fact that eigenvalue_multiplicity overestimates the multiplicities
    ## this asserts that the computed multiplicities are correct
    assert sum(ST_ev_multiplicity) == subspace_dimension

    T_evs = [
        ZZ((zeta_order * disc_quadratic(*a)) % zeta_order) / zeta_order
        for a in (singls + pairs if plus_basis else pairs)
    ]

    return subspace_dimension * (1 + QQ(k) / 12) \
           - ZZ(sum( (ST_ev_multiplicity[n] * ((-2 * k - n) % 12)) for n in range(12) )) / 12 \
           - ZZ(sum( (S_ev_multiplicity[n] * ((2 * k + n) % 8)) for n in range(8) )) / 8 \
           - sum(T_evs)