<commit_before>'''
Collection of standard functions.

This method provides functions like inner products, norms, ...
'''

import numpy
from scipy.sparse.linalg import LinearOperator
from scipy.sparse import issparse
from scipy.linalg import eigh

# ===================================================================
def ip(X,Y):
    '''Euclidean inner product.

    numpy.vdot only works for vectors and numpy.dot does not use the conjugate
    transpose. In Octave/MATLAB notation ip(X,Y) == X'*Y.

    Arguments:
        X:  array of shape [N,m]
        Y:  array of shape [N,n]

    Returns:
        ip: array of shape [m,n] with X^H * Y
    '''
    return numpy.dot(X.T.conj(), Y)

# ===================================================================
def norm_squared( x, Mx = None, inner_product = ip ):
    '''Compute the norm^2 w.r.t. to a given scalar product.'''
    assert( len(x.shape)==2 )
    assert( x.shape[1]==1 )
    if Mx is None:
        rho = inner_product(x, x)[0,0]
    else:
        assert( len(Mx.shape)==2 )
        assert( Mx.shape[1]==1 )
        rho = inner_product(x, Mx)[0,0]

#    if rho.imag != 0.0: #abs(rho.imag) > abs(rho) * 1.0e-10:
    if abs(rho.imag) > abs(rho) *1e-10:
        raise ValueError( 'M not positive definite?' )

    rho = rho.real

    if rho < 0.0:
        raise ValueError( '<x,Mx> = %g. M not positive definite?' % rho )

    return rho

# ===================================================================
def norm( x, Mx = None, inner_product = ip ):
    '''Compute the norm w.r.t. to a given scalar product.'''
    return numpy.sqrt(norm_squared( x, Mx = Mx, inner_product = inner_product ) )

# ===================================================================
def apply( A, x ):
    '''Implement A*x for different types of linear operators.'''
    if A is None:
        return x
    elif isinstance( A, numpy.ndarray ):
        return numpy.dot( A, x )
    elif scipy.sparse.isspmatrix(A):
        return A * x
    elif isinstance( A, scipy.sparse.linalg.LinearOperator ):
        return A * x
    else:
        raise ValueError( 'Unknown operator type "%s".' % type(A) )

# ===================================================================
def norm_MMlr(M, Ml, A, Mr, b, x0, yk, inner_product = ip):
    xk = x0 + apply(Mr, yk)
    r = b - apply(A, xk)
    Mlr = apply(Ml, r)
    # normalize residual before applying the preconditioner here.
    # otherwise MMlr can become 0 exactly (pyamg doesnt respect relative
    # residual)
    # TODO for testing: 2-norm
    norm_Mlr = norm(Mlr)
    if norm_Mlr == 0:
        MMlr = numpy.zeros( Mlr.shape )
        norm_MMlr = 0
    else:
        nMlr = Mlr / norm_Mlr
        nMMlr = apply(M, nMlr)
        MMlr = nMMlr * norm_Mlr
        norm_MMlr = norm(Mlr, MMlr, inner_product=inner_product)
    # return xk and ||M*Ml*(b-A*(x0+Mr*yk))||_{M^{-1}}
    return xk, Mlr, MMlr, norm_MMlr

# ===================================================================
def givens(a, b):
    '''Givens rotation
    [   c       s    ] * [a] = [r]
    [-conj(s) conj(c)]   [b]   [0]
    r real and non-negative.'''
    if abs(b) == 0:
        r = abs(a)
        c = a.conjugate() / r
        s = 0
    elif abs(a) == 0:
        r = abs(b)
        c = 0
        s = b.conjugate() / r
    elif abs(b) > abs(a):
        absb = abs(b)
        t = a.conjugate() / absb
        u = numpy.sqrt(1 + t.real**2 + t.imag**2)
        c = t / u
        s = (b.conjugate()/absb) / u
        r = absb * u
    else:
        absa = abs(a)
        t = b.conjugate()/absa
        u = numpy.sqrt(1 + t.real**2 + t.imag**2)
        c = (a.conjugate()/absa)/u
        s = t/u
        r = absa*u
    return numpy.array([[c, s],
                     [-s.conjugate(), c.conjugate()]])

# ===================================================================
def get_projection(b, W, AW,
        # TODO: AW optional, supply A
        x0 = None,
        inner_product = ip):
    """Get projection and appropriate initial guess for use in deflated methods.

    Arguments:
        W:  the basis vectors used for deflation (Nxk array).
        AW: A*W, where A is the operator of the linear algebraic system to be
            deflated. A has to be self-adjoint w.r.t. inner_product. Do not
            include the positive-definite preconditioner (argument M in MINRES)
            here. Let N be the dimension of the vector space the operator is
            defined on.
        b:  the right hand side of the linear system (array of length N).
        x0: the initial guess (array of length N).
        inner_product: the inner product also used for the deflated iterative
            method.

    Returns:
        P:  the projection to be used as _right_ preconditioner (e.g. Mr=P in
            MINRES). The preconditioned operator A*P is self-adjoint w.r.t.
            inner_product.
            P(x)=x - W*inner_product(W, A*W)^{-1}*inner_product(A*W, x)
        x0new: an adapted initial guess s.t. the deflated iterative solver
            does not break down (in exact arithmetics).
        AW: AW=A*W. This is returned in order to reduce the total number of
            matrix-vector multiplications with A.

    For nW = W.shape[1] = AW.shape[1] the computational cost is
    cost(get_projection): 2*cost(Pfun) + (nW^2)*IP
    cost(Pfun): nW*IP + (2/3)*nW^3 + nW*AXPY
    """
    # --------------------------------------------------------------------------
    def Pfun(x):
        '''Computes x - W * E\<AW,x>.'''
        return x - numpy.dot(W, numpy.dot(Einv, inner_product(AW, x)))
    # --------------------------------------------------------------------------

    # cost: (nW^2)*IP
    E = inner_product(W, AW)
    Einv = numpy.linalg.inv(E)

    # cost: nW*IP + (2/3)*nW^3
    EWb = numpy.dot(Einv, inner_product(W, b))

    # Define projection operator.
    N = len(b)
    dtype = upcast(W.dtype, AW.dtype, b.dtype, x0.dtype)
    P = scipy.sparse.linalg.LinearOperator( [N,N], Pfun, matmat=Pfun,
                                            dtype=dtype)
    # Get updated x0.
    # cost: nW*AXPY + cost(Pfun)
    x0new = P*x0 +  numpy.dot(W, EWb)

    return P, x0new

# ===================================================================
def ritzh(Vfull, Hfull,
               W = None,
               AW = None,
               A = None,
               M = None,
               Minv = None,
               inner_product = ip,
               ):
    """Compute Ritz pairs from a (possibly deflated) Lanczos procedure.

    Arguments
        W:  a Nxk array. W's columns must be orthonormal w.r.t. the
            M-inner-product (inner_product(M^{-1} W, W) = I_k).
        AW: contains the result of A applied to W (passed in order to reduce #
            of matrix-vector multiplications with A).
        Vfull: a Nxn array. Vfull's columns must be orthonormal w.r.t. the
            M-inner-product. Vfull and Hfull must be created with a (possibly
            deflated) Lanczos procedure (e.g. CG/MINRES). For example, Vfull
            and Hfull can be obtained from MINRES applied to a linear system
            with the operator A, the inner product inner_product, the HPD
            preconditioner M and the right preconditioner Mr set to the
            projection obtained with get_projection(W, AW, ...).
        Hfull: see Vfull.
        M:  The preconditioner used in the Lanczos procedure.

        The arguments thus have to fulfill the following equations:
            AW = A*W.
            M*A*Mr*Vfull[:,0:-1] = Vfull*Hfull,
                 where Mr=get_projection(W, AW,...,inner_product).
            inner_product( M^{-1} [W,Vfull], [W,Vfull] ) = I_{k+n}.

    Returns:
        ritz_vals: an array with n+k Ritz values.
        ritz_coeffs: a (n+k)x(n+k) array where the ritz_coeffs[:,i] are the
            coefficients (in the basis [W,Vfull]) of the vector corresponding
            the Ritz value ritz_vals[i]. The Ritz vectors then also are
            orthonormal w.r.t. the M-inner-product, that is inner_product(
            M^{-1}*ritz_vecs, ritz_vecs ) = I_{k+n}.
        ritz_res_norm: an array with n+k residual norms. ritz_res_norm[i] is
            the M^{-1}-norm of the residual
                M*A*ritz_vecs[:,i] - ritz_vals[i]*ritz_vecs[:,i].
            ritz_vals, ritz_vecs and norm_ritz_res are sorted s.t. the
            residual norms are ascending.

    Under the above assumptions, [W, Vfull] is orthonormal w.r.t. the
    M-inner-product. Then the Ritz pairs w.r.t. the operator M*A, the basis [W,
    Vfull[:,0:-1]] and the M-inner-product are computed. Also the M-norm of the
    Ritz pair residual is computed. The computation of the residual norms do
    not need the application of the operator A, but the preconditioner has to
    be applied to the basis W. The computation of the residual norm may be
    unstable (it seems as if residual norms below 1e-8 cannot be achieved...
    note that the actual residual may be lower!).
    """
    N = Vfull.shape[0]
    nVfull = Vfull.shape[1]
    nW = 0 if W is None else W.shape[1]
    # total number ritz vectors
    nritz = nW + nVfull - 1

    if issparse(Hfull):
        Hfull = Hfull.todense()

    if nW > 0:
        B1 = inner_product(AW, Vfull)   # can (and should) be obtained from projection

        E = inner_product(W, AW)        # ~
        Einv = numpy.linalg.inv(E) # can (and should) be obtained from earlier computation
        # Apply preconditioner to AW (I don't see a way to get rid of this! -- André).
        # cost: nW*APPLM
        MAW = apply(M, AW)
    else:
        W = numpy.zeros((N,0))
        AW = numpy.zeros((N,0))
        B1 = numpy.zeros((0,nVfull))
        E = numpy.zeros((0, 0))
        Einv = numpy.zeros((0, 0))
        MAW = numpy.zeros((W.shape[0], 0))

    B = B1[:, 0:-1]

    # Stack matrices appropriately: [E, B;
    #                                B', Hfull(1:end-1,:) + B'*Einv*B].
    ritzmat = numpy.r_[ numpy.c_[E,          B],
                     numpy.c_[B.T.conj(), Hfull[0:-1,:] + numpy.dot(B.T.conj(), numpy.dot(Einv, B))]
                   ]
    # Compute Ritz values / vectors.
    ritz_values, ritz_coeffs = eigh(ritzmat)

    # Calculate the Ritz-residuals in a smart way.
    ritz_res_norm = numpy.empty(nritz)
    D = inner_product(AW, MAW)
    for i in range(nritz):
        w = ritz_coeffs[:W.shape[1],[i]]
        v = ritz_coeffs[W.shape[1]:,[i]]
        mu = ritz_values[i]

        # The following computes  <z, CC*z>_2  with
        #
        #z = numpy.r_[ -mu*w,
        #            w + numpy.dot(Einv, numpy.dot(B, v)),
        #            numpy.dot(Hfull, v) - numpy.r_[mu*v, numpy.zeros((1,1))] ]
        #z = numpy.reshape(z, (z.shape[0],1))
        # cost: (nW^2)*IP
        #zeros = numpy.zeros((nW,nVfull))
        #CC = numpy.r_[ numpy.c_[ numpy.eye(nW),     E,           zeros],
        #            numpy.c_[ E.T.conj(),     D,           B1],
        #            numpy.c_[ zeros.T.conj(), B1.T.conj(), numpy.eye(nVfull)]
        #          ]
        #
        # Attention:
        # CC should be HPD (and thus $<z, CC*z>_2 > 0$).
        # However, this only holds if the preconditioner M was solved exactly
        # (then inner_product(Minv*W,W)=I).
        # In this case, the computation seems to be stable.
        z0 = -mu * w
        z1 = w + numpy.dot(Einv, numpy.dot(B, v))
        z2 = numpy.dot(Hfull, v) - numpy.r_[mu*v, numpy.zeros((1,1))]
        res_ip = ip(z0, z0) + 2 * ip(z0, numpy.dot(E, z1)).real + ip(z1, numpy.dot(D, z1)) \
               + 2 * ip(z1, numpy.dot(B1, z2)).real + ip(z2, z2)
        res_ip = res_ip[0,0]

        if res_ip.imag > 1e-13:
            warnings.warn('res_ip.imag = %g > 1e-13. Preconditioner not symmetric?' % res_ip.imag)
        if res_ip.real < -1e-10:
            warnings.warn('res_ip.real = %g > 1e-10. Make sure that the basis is linearly independent and the preconditioner is solved \'exactly enough\'.' % res_ip.real)
        ritz_res_norm[i] = numpy.sqrt(abs(res_ip))

        # Explicit computation of residual (this part only works for M=I)
        #X = numpy.c_[W, Vfull[:,0:-1]]
        #V = numpy.dot(X, numpy.r_[w,v])
        #MAV = _apply(M,_apply(A, V))
        #res_explicit = MAV - ritz_values[i]*V
        #zz = inner_product(_apply(Minv, res_explicit), res_explicit)[0,0]
        #assert( zz.imag<1e-13 )
        #print abs(norm_ritz_res[i] - numpy.sqrt(abs(zz)))
        #print 'Explicit residual: %g' % numpy.sqrt(abs(zz))

    return ritz_values, ritz_coeffs, ritz_res_norm
<commit_msg>fix get_projection if x0 is None<commit_after>'''
Collection of standard functions.

This method provides functions like inner products, norms, ...
'''

import numpy
from scipy.sparse import issparse, isspmatrix
from scipy.sparse.linalg import LinearOperator
from scipy.sparse.sputils import upcast
from scipy.linalg import eigh

# ===================================================================
def ip(X,Y):
    '''Euclidean inner product.

    numpy.vdot only works for vectors and numpy.dot does not use the conjugate
    transpose. In Octave/MATLAB notation ip(X,Y) == X'*Y.

    Arguments:
        X:  array of shape [N,m]
        Y:  array of shape [N,n]

    Returns:
        ip: array of shape [m,n] with X^H * Y
    '''
    return numpy.dot(X.T.conj(), Y)

# ===================================================================
def norm_squared( x, Mx = None, inner_product = ip ):
    '''Compute the norm^2 w.r.t. to a given scalar product.'''
    assert( len(x.shape)==2 )
    assert( x.shape[1]==1 )
    if Mx is None:
        rho = inner_product(x, x)[0,0]
    else:
        assert( len(Mx.shape)==2 )
        assert( Mx.shape[1]==1 )
        rho = inner_product(x, Mx)[0,0]

#    if rho.imag != 0.0: #abs(rho.imag) > abs(rho) * 1.0e-10:
    if abs(rho.imag) > abs(rho) *1e-10:
        raise ValueError( 'M not positive definite?' )

    rho = rho.real

    if rho < 0.0:
        raise ValueError( '<x,Mx> = %g. M not positive definite?' % rho )

    return rho

# ===================================================================
def norm( x, Mx = None, inner_product = ip ):
    '''Compute the norm w.r.t. to a given scalar product.'''
    return numpy.sqrt(norm_squared( x, Mx = Mx, inner_product = inner_product ) )

# ===================================================================
def apply( A, x ):
    '''Implement A*x for different types of linear operators.'''
    if A is None:
        return x
    elif isinstance( A, numpy.ndarray ):
        return numpy.dot( A, x )
    elif isspmatrix(A):
        return A * x
    elif isinstance( A, LinearOperator ):
        return A * x
    else:
        raise ValueError( 'Unknown operator type "%s".' % type(A) )

# ===================================================================
def norm_MMlr(M, Ml, A, Mr, b, x0, yk, inner_product = ip):
    xk = x0 + apply(Mr, yk)
    r = b - apply(A, xk)
    Mlr = apply(Ml, r)
    # normalize residual before applying the preconditioner here.
    # otherwise MMlr can become 0 exactly (pyamg doesnt respect relative
    # residual)
    # TODO for testing: 2-norm
    norm_Mlr = norm(Mlr)
    if norm_Mlr == 0:
        MMlr = numpy.zeros( Mlr.shape )
        norm_MMlr = 0
    else:
        nMlr = Mlr / norm_Mlr
        nMMlr = apply(M, nMlr)
        MMlr = nMMlr * norm_Mlr
        norm_MMlr = norm(Mlr, MMlr, inner_product=inner_product)
    # return xk and ||M*Ml*(b-A*(x0+Mr*yk))||_{M^{-1}}
    return xk, Mlr, MMlr, norm_MMlr

# ===================================================================
def givens(a, b):
    '''Givens rotation
    [   c       s    ] * [a] = [r]
    [-conj(s) conj(c)]   [b]   [0]
    r real and non-negative.'''
    if abs(b) == 0:
        r = abs(a)
        c = a.conjugate() / r
        s = 0
    elif abs(a) == 0:
        r = abs(b)
        c = 0
        s = b.conjugate() / r
    elif abs(b) > abs(a):
        absb = abs(b)
        t = a.conjugate() / absb
        u = numpy.sqrt(1 + t.real**2 + t.imag**2)
        c = t / u
        s = (b.conjugate()/absb) / u
        r = absb * u
    else:
        absa = abs(a)
        t = b.conjugate()/absa
        u = numpy.sqrt(1 + t.real**2 + t.imag**2)
        c = (a.conjugate()/absa)/u
        s = t/u
        r = absa*u
    return numpy.array([[c, s],
                     [-s.conjugate(), c.conjugate()]])

# ===================================================================
def get_projection(b, W, AW,
        # TODO: AW optional, supply A
        x0 = None,
        inner_product = ip):
    """Get projection and appropriate initial guess for use in deflated methods.

    Arguments:
        W:  the basis vectors used for deflation (Nxk array).
        AW: A*W, where A is the operator of the linear algebraic system to be
            deflated. A has to be self-adjoint w.r.t. inner_product. Do not
            include the positive-definite preconditioner (argument M in MINRES)
            here. Let N be the dimension of the vector space the operator is
            defined on.
        b:  the right hand side of the linear system (array of length N).
        x0: the initial guess (array of length N).
        inner_product: the inner product also used for the deflated iterative
            method.

    Returns:
        P:  the projection to be used as _right_ preconditioner (e.g. Mr=P in
            MINRES). The preconditioned operator A*P is self-adjoint w.r.t.
            inner_product.
            P(x)=x - W*inner_product(W, A*W)^{-1}*inner_product(A*W, x)
        x0new: an adapted initial guess s.t. the deflated iterative solver
            does not break down (in exact arithmetics).
        AW: AW=A*W. This is returned in order to reduce the total number of
            matrix-vector multiplications with A.

    For nW = W.shape[1] = AW.shape[1] the computational cost is
    cost(get_projection): 2*cost(Pfun) + (nW^2)*IP
    cost(Pfun): nW*IP + (2/3)*nW^3 + nW*AXPY
    """
    # --------------------------------------------------------------------------
    def Pfun(x):
        '''Computes x - W * E\<AW,x>.'''
        return x - numpy.dot(W, numpy.dot(Einv, inner_product(AW, x)))
    # --------------------------------------------------------------------------

    # cost: (nW^2)*IP
    E = inner_product(W, AW)
    Einv = numpy.linalg.inv(E)

    # cost: nW*IP + (2/3)*nW^3
    EWb = numpy.dot(Einv, inner_product(W, b))

    # Define projection operator.
    N = len(b)
    if x0 is None:
        x0 = numpy.zeros((N,1))
    dtype = upcast(W.dtype, AW.dtype, b.dtype, x0.dtype)
    P = LinearOperator( [N,N], Pfun, matmat=Pfun,
                                            dtype=dtype)
    # Get updated x0.
    # cost: nW*AXPY + cost(Pfun)
    x0new = P*x0 +  numpy.dot(W, EWb)

    return P, x0new

# ===================================================================
def ritzh(Vfull, Hfull,
               W = None,
               AW = None,
               A = None,
               M = None,
               Minv = None,
               inner_product = ip,
               ):
    """Compute Ritz pairs from a (possibly deflated) Lanczos procedure.

    Arguments
        W:  a Nxk array. W's columns must be orthonormal w.r.t. the
            M-inner-product (inner_product(M^{-1} W, W) = I_k).
        AW: contains the result of A applied to W (passed in order to reduce #
            of matrix-vector multiplications with A).
        Vfull: a Nxn array. Vfull's columns must be orthonormal w.r.t. the
            M-inner-product. Vfull and Hfull must be created with a (possibly
            deflated) Lanczos procedure (e.g. CG/MINRES). For example, Vfull
            and Hfull can be obtained from MINRES applied to a linear system
            with the operator A, the inner product inner_product, the HPD
            preconditioner M and the right preconditioner Mr set to the
            projection obtained with get_projection(W, AW, ...).
        Hfull: see Vfull.
        M:  The preconditioner used in the Lanczos procedure.

        The arguments thus have to fulfill the following equations:
            AW = A*W.
            M*A*Mr*Vfull[:,0:-1] = Vfull*Hfull,
                 where Mr=get_projection(W, AW,...,inner_product).
            inner_product( M^{-1} [W,Vfull], [W,Vfull] ) = I_{k+n}.

    Returns:
        ritz_vals: an array with n+k Ritz values.
        ritz_coeffs: a (n+k)x(n+k) array where the ritz_coeffs[:,i] are the
            coefficients (in the basis [W,Vfull]) of the vector corresponding
            the Ritz value ritz_vals[i]. The Ritz vectors then also are
            orthonormal w.r.t. the M-inner-product, that is inner_product(
            M^{-1}*ritz_vecs, ritz_vecs ) = I_{k+n}.
        ritz_res_norm: an array with n+k residual norms. ritz_res_norm[i] is
            the M^{-1}-norm of the residual
                M*A*ritz_vecs[:,i] - ritz_vals[i]*ritz_vecs[:,i].
            ritz_vals, ritz_vecs and norm_ritz_res are sorted s.t. the
            residual norms are ascending.

    Under the above assumptions, [W, Vfull] is orthonormal w.r.t. the
    M-inner-product. Then the Ritz pairs w.r.t. the operator M*A, the basis [W,
    Vfull[:,0:-1]] and the M-inner-product are computed. Also the M-norm of the
    Ritz pair residual is computed. The computation of the residual norms do
    not need the application of the operator A, but the preconditioner has to
    be applied to the basis W. The computation of the residual norm may be
    unstable (it seems as if residual norms below 1e-8 cannot be achieved...
    note that the actual residual may be lower!).
    """
    N = Vfull.shape[0]
    nVfull = Vfull.shape[1]
    nW = 0 if W is None else W.shape[1]
    # total number ritz vectors
    nritz = nW + nVfull - 1

    if issparse(Hfull):
        Hfull = Hfull.todense()

    if nW > 0:
        B1 = inner_product(AW, Vfull)   # can (and should) be obtained from projection

        E = inner_product(W, AW)        # ~
        Einv = numpy.linalg.inv(E) # can (and should) be obtained from earlier computation
        # Apply preconditioner to AW (I don't see a way to get rid of this! -- André).
        # cost: nW*APPLM
        MAW = apply(M, AW)
    else:
        W = numpy.zeros((N,0))
        AW = numpy.zeros((N,0))
        B1 = numpy.zeros((0,nVfull))
        E = numpy.zeros((0, 0))
        Einv = numpy.zeros((0, 0))
        MAW = numpy.zeros((W.shape[0], 0))

    B = B1[:, 0:-1]

    # Stack matrices appropriately: [E, B;
    #                                B', Hfull(1:end-1,:) + B'*Einv*B].
    ritzmat = numpy.r_[ numpy.c_[E,          B],
                     numpy.c_[B.T.conj(), Hfull[0:-1,:] + numpy.dot(B.T.conj(), numpy.dot(Einv, B))]
                   ]
    # Compute Ritz values / vectors.
    ritz_values, ritz_coeffs = eigh(ritzmat)

    # Calculate the Ritz-residuals in a smart way.
    ritz_res_norm = numpy.empty(nritz)
    D = inner_product(AW, MAW)
    for i in range(nritz):
        w = ritz_coeffs[:W.shape[1],[i]]
        v = ritz_coeffs[W.shape[1]:,[i]]
        mu = ritz_values[i]

        # The following computes  <z, CC*z>_2  with
        #
        #z = numpy.r_[ -mu*w,
        #            w + numpy.dot(Einv, numpy.dot(B, v)),
        #            numpy.dot(Hfull, v) - numpy.r_[mu*v, numpy.zeros((1,1))] ]
        #z = numpy.reshape(z, (z.shape[0],1))
        # cost: (nW^2)*IP
        #zeros = numpy.zeros((nW,nVfull))
        #CC = numpy.r_[ numpy.c_[ numpy.eye(nW),     E,           zeros],
        #            numpy.c_[ E.T.conj(),     D,           B1],
        #            numpy.c_[ zeros.T.conj(), B1.T.conj(), numpy.eye(nVfull)]
        #          ]
        #
        # Attention:
        # CC should be HPD (and thus $<z, CC*z>_2 > 0$).
        # However, this only holds if the preconditioner M was solved exactly
        # (then inner_product(Minv*W,W)=I).
        # In this case, the computation seems to be stable.
        z0 = -mu * w
        z1 = w + numpy.dot(Einv, numpy.dot(B, v))
        z2 = numpy.dot(Hfull, v) - numpy.r_[mu*v, numpy.zeros((1,1))]
        res_ip = ip(z0, z0) + 2 * ip(z0, numpy.dot(E, z1)).real + ip(z1, numpy.dot(D, z1)) \
               + 2 * ip(z1, numpy.dot(B1, z2)).real + ip(z2, z2)
        res_ip = res_ip[0,0]

        if res_ip.imag > 1e-13:
            warnings.warn('res_ip.imag = %g > 1e-13. Preconditioner not symmetric?' % res_ip.imag)
        if res_ip.real < -1e-10:
            warnings.warn('res_ip.real = %g > 1e-10. Make sure that the basis is linearly independent and the preconditioner is solved \'exactly enough\'.' % res_ip.real)
        ritz_res_norm[i] = numpy.sqrt(abs(res_ip))

        # Explicit computation of residual (this part only works for M=I)
        #X = numpy.c_[W, Vfull[:,0:-1]]
        #V = numpy.dot(X, numpy.r_[w,v])
        #MAV = _apply(M,_apply(A, V))
        #res_explicit = MAV - ritz_values[i]*V
        #zz = inner_product(_apply(Minv, res_explicit), res_explicit)[0,0]
        #assert( zz.imag<1e-13 )
        #print abs(norm_ritz_res[i] - numpy.sqrt(abs(zz)))
        #print 'Explicit residual: %g' % numpy.sqrt(abs(zz))

    return ritz_values, ritz_coeffs, ritz_res_norm
<|endoftext|>


<commit_before>import logging

from kuyruk.queue import Queue

logger = logging.getLogger(__name__)

class Task(object):

    def __init__(self, f, kuyruk, queue='kuyruk'):
        self.f = f
        self.kuyruk = kuyruk
        self.queue_name = queue

    def __repr__(self):
        return "<Task %s>" % self.fully_qualified_name

    def __call__(self, *args, **kwargs):
        fname = self.fully_qualified_name
        logger.debug('fname: %s', fname)
        if self.kuyruk.eager:
            self.f(*args, **kwargs)
        else:
            queue = Queue(self.queue_name, self.kuyruk.connection)
            queue.send({'fname': fname, 'args': args, 'kwargs': kwargs})
            queue.close()

    @property
    def fully_qualified_name(self):
        return "%s.%s" % (self.f.__module__, self.f.__name__)
<commit_msg>classmethod support<commit_after>import inspect
import logging

from kuyruk.queue import Queue

logger = logging.getLogger(__name__)

class Task(object):

    def __init__(self, f, kuyruk, queue='kuyruk'):
        self.f = f
        self.kuyruk = kuyruk
        self.queue_name = queue

    def __repr__(self):
        return "<Task %s>" % self.fully_qualified_name

    def __call__(self, *args, **kwargs):
        fname = self.fully_qualified_name
        logger.debug('fname: %s', fname)
        if self.kuyruk.eager:
            self.f(*args, **kwargs)
        else:
            queue = Queue(self.queue_name, self.kuyruk.connection)
            queue.send({'fname': fname, 'args': args, 'kwargs': kwargs})
            queue.close()

    @property
    def fully_qualified_name(self):
        f = self.f
        if inspect.ismethod(f):
            return f.__module__ + '.' + f.__self__.__name__ + '.' + f.__name__
        else:
            return f.__module__ + '.' + f.__name__
<|endoftext|>


<commit_before>#!/usr/bin/env python
# encoding: utf-8

import os
import sys
import unittest

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

import pfp
import pfp.fields
import pfp.interp
import pfp.utils

import utils

class TestStructUnion(utils.PfpTestCase):
    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_struct_vit9696_1(self):
        dom = self._test_parse_build(
            "\x00\x01\x02\x03\x00\x01\x02\x03",
            """
                typedef struct MY_STRUCT_S {
                    char magic[4];
                    unsigned int filesize;
                } MY_STRUCT;
                LittleEndian();
                MY_STRUCT s;
            """
        )
        assert dom.s.magic == "\x00\x01\x02\x03"
        assert dom.s.filesize == 0x03020100

    def test_struct_vit9696_2(self):
        dom = self._test_parse_build(
            "\x00\x01\x02\x03\x00\x01\x02\x03",
            """
                struct MY_STRUCT {
                    char magic[4];
                    unsigned int filesize;
                };
                LittleEndian();
                MY_STRUCT s;
            """
        )
        assert dom.s.magic == "\x00\x01\x02\x03"
        assert dom.s.filesize == 0x03020100

    def test_struct_vit9696_3(self):
        dom = self._test_parse_build(
            "\x00\x01\x02\x03\x00\x01\x02\x03",
            """
                typedef struct MY_STRUCT {
                    char magic[4];
                    unsigned int filesize;
                };
                LittleEndian();
                MY_STRUCT s;
            """
        )
        assert dom.s.magic == "\x00\x01\x02\x03"
        assert dom.s.filesize == 0x03020100

    def test_struct_vit9696_4(self):
        dom = self._test_parse_build(
            "\x00\x01\x02\x03\x00\x01\x02\x03",
            """
                struct MY_STRUCT {
                    char magic[4];
                    unsigned int filesize;
                };
                LittleEndian();
                struct MY_STRUCT s;
            """
        )
        assert dom.s.magic == "\x00\x01\x02\x03"
        assert dom.s.filesize == 0x03020100

    def test_struct_vit9696_5(self):
        dom = self._test_parse_build(
            "\x00\x01\x02\x03\x00\x01\x02\x03",
            """
                struct MY_STRUCT {
                    char magic[4];
                    unsigned int filesize;
                };
                typedef struct MY_STRUCT ME;
                LittleEndian();
                ME s;
            """,
            debug=True,
        )
        assert dom.s.magic == "\x00\x01\x02\x03"
        assert dom.s.filesize == 0x03020100

    def test_basic_struct(self):
        dom = self._test_parse_build(
            "\x00\x01\x02\x03",
            """
                struct SomeStruct {
                    byte a;
                    byte b;
                    byte c;
                    byte d;
                };
                struct SomeStruct test;
            """
        )
        assert dom.test.a == 0
        assert dom.test.b == 1
        assert dom.test.c == 2
        assert dom.test.d == 3

    def test_field_path(self):
        dom = self._test_parse_build(
            "Abbbb4141414142424242",
            """
                struct {
                    struct {
                        struct {
                            char inner;
                            char array[4];
                        } nested2;
                        int some_int;
                    } nested1;
                    int some_int2;
                } root;
            """,
        )
        self.assertEqual(dom.root._pfp__path(), "root")
        self.assertEqual(dom.root.some_int2._pfp__path(), "root.some_int2")
        self.assertEqual(dom.root.nested1._pfp__path(), "root.nested1")
        self.assertEqual(dom.root.nested1.some_int._pfp__path(), "root.nested1.some_int")
        self.assertEqual(dom.root.nested1.nested2._pfp__path(), "root.nested1.nested2")
        self.assertEqual(dom.root.nested1.nested2.inner._pfp__path(), "root.nested1.nested2.inner")
        self.assertEqual(dom.root.nested1.nested2.array._pfp__path(), "root.nested1.nested2.array")
        self.assertEqual(dom.root.nested1.nested2.array[0]._pfp__path(), "root.nested1.nested2.array[0]")
        self.assertEqual(dom.root.nested1.nested2.array[1]._pfp__path(), "root.nested1.nested2.array[1]")
        self.assertEqual(dom.root.nested1.nested2.array[2]._pfp__path(), "root.nested1.nested2.array[2]")
        self.assertEqual(dom.root.nested1.nested2.array[3]._pfp__path(), "root.nested1.nested2.array[3]")

    def test_struct(self):
        dom = self._test_parse_build(
            "abcddcba",
            """
                typedef struct {
                    int some_int;
                } blah;

                blah some_struct;
                blah some_struct2;
            """,
        )

    def test_forward_declared_struct(self):
        dom = self._test_parse_build(
            "\x00\x01",
            """
                struct fp16;
                void ReadFP16(fp16& f)
                {
                    Printf("%d", f.value);
                }
                typedef struct
                {
                    int16 value;
                } fp16;
                fp16 preferred_volume;
                ReadFP16(preferred_volume);
            """,
            stdout="256",
        )

    def test_struct_with_parameters(self):
        dom = self._test_parse_build(
            "aabbb",
            """
                typedef struct (int a, int b) {
                    char chars1[a];
                    char chars2[b];
                } blah;

                blah test(2, 3);
            """,
        )
        self.assertEqual(dom.test.chars1, "aa")
        self.assertEqual(dom.test.chars2, "bbb")

    def test_struct_with_parameters2(self):
        # ``descr_length l(bytes)`` is being treated as a function
        # declaration!
        dom = self._test_parse_build(
            "\x01\x02\x03\x04",
            """
                typedef struct (int arraySize)
                {
                    uchar b[arraySize];
                } descr_length <read=descr_format>;

                local int bytes = 4;
                descr_length l(bytes);
            """,
        )
        self.assertEqual(len(dom.l.b), 4)
        self.assertEqual(dom.l.b[0], 1)
        self.assertEqual(dom.l.b[1], 2)
        self.assertEqual(dom.l.b[2], 3)
        self.assertEqual(dom.l.b[3], 4)

    def test_struct_with_parameters3(self):
        # ``descr_length l(bytes)`` is being treated as a function
        # declaration!
        dom = self._test_parse_build(
            "\x01\x02\x03\x04\x01\x02\x03",
            """
                typedef struct (int arraySize, int arraySize2)
                {
                    uchar b[arraySize];
                    uchar c[arraySize2];
                } descr_length <read=descr_format>;

                local int bytes = 4;
                descr_length l(bytes, 3);
            """,
        )
        self.assertEqual(len(dom.l.b), 4)
        self.assertEqual(dom.l.b[0], 1)
        self.assertEqual(dom.l.b[1], 2)
        self.assertEqual(dom.l.b[2], 3)
        self.assertEqual(dom.l.b[3], 4)
        self.assertEqual(len(dom.l.c), 3)
        self.assertEqual(dom.l.c[0], 1)
        self.assertEqual(dom.l.c[1], 2)
        self.assertEqual(dom.l.c[2], 3)

    def test_struct_decl_with_struct_keyword(self):
        dom = self._test_parse_build(
            "ABCD",
            """
                typedef struct {
                    char a;
                    char b;
                    char c;
                    char d;
                } BLAH;

                struct BLAH decldStruct;
            """,
        )

        self.assertEqual(dom.decldStruct.a, ord("A"))
        self.assertEqual(dom.decldStruct.b, ord("B"))
        self.assertEqual(dom.decldStruct.c, ord("C"))
        self.assertEqual(dom.decldStruct.d, ord("D"))

    def test_struct_initialization(self):
        # local structs aren't allowed!!!
        return

    #        dom = self._test_parse_build(
    #            "",
    #            """
    #                typedef struct {
    #                    char a;
    #                    char b;
    #                    char c;
    #                    char d;
    #                } blah;
    #
    #                local blah some_struct = { 'a', 'b', 'c', 'd'};
    #            """
    #        )

    def test_union(self):
        dom = self._test_parse_build(
            "abcd",
            """
                typedef union {
                    int some_int;
                    struct {
                        char a;
                        char b;
                        char c;
                        char d;
                    } some_chars;
                } blah;

                blah some_union;
            """,
        )

    def test_union_complex(self):
        dom = self._test_parse_build(
            "\x00abcd",
            """
                typedef struct {
                    uchar a;
                    uchar b;
                    uchar c;
                    uchar d;
                } TEST;

                struct {
                    uchar blah;
                    union {
                        TEST chars;
                        uchar raw[sizeof(chars)];
                    } onion;
                } test;
            """,
        )
        self.assertEqual(dom.test.onion.raw, "abcd")
        self.assertEqual(dom.test.onion.chars.a, ord("a"))
        self.assertEqual(dom.test.onion.chars.b, ord("b"))
        self.assertEqual(dom.test.onion.chars.c, ord("c"))
        self.assertEqual(dom.test.onion.chars.d, ord("d"))

    def test_union_offset1(self):
        dom = self._test_parse_build(
            "abcd",
            """
                struct {
                    char a;
                    char b;
                    union {
                        char c;
                        uchar uc;
                    } union_test;
                    char d;
                } test;
            """,
        )
        self.assertEqual(dom.test.union_test._pfp__offset, 2)

    def test_union_offset2(self):
        dom = self._test_parse_build(
            "abcd",
            """
                typedef union {
                    char c;
                    uchar uc;
                } CHAR_UNION;

                struct {
                    char a;
                    char b;
                    CHAR_UNION union_test;
                    char d;
                } test;
            """,
        )
        self.assertEqual(dom.test.union_test._pfp__offset, 2)

    def test_auto_increment_field_names(self):
        # when a field is declared multiple times with the same name, but
        # not consecutively, the fields should get a sequential number assigned
        # to them and NOT be stored in an implicit array
        dom = self._test_parse_build(
            "a\x00\x010\x00\x02",
            """
                BigEndian();
                while(!FEof()) {
                    char header;
                    short val;
                }
            """,
        )

        self.assertEqual(dom.header_0, ord("a"))
        self.assertEqual(dom.val_0, 1)

        self.assertEqual(dom.header_1, ord("0"))
        self.assertEqual(dom.val_1, 2)

    def test_auto_increment_but_still_reference_last_decl_normal(self):
        # this is an interesting behavior of 010 scripts. When a field
        # is repeatedly declared, 010 scripts do not append a suffix to
        # the field names. However, since our goal is manipulation and being
        # able to access these fields individually, we do add a suffix.
        # the problem is that the script still needs to be able to access
        # the last declared field by the original name and not the
        # suffixed one.
        dom = self._test_parse_build(
            "\x01a\x01b\x01c",
            """
                while(!FEof()) {
                    char length;
                    char str[length];
                    Printf("%s|", str);
                }
            """,
            stdout="a|b|c|",
        )

    def test_implicit_array_dot_notation_for_last(self):
        # I BELIEVE scripts are able to access implicit array items
        # by index OR directly access the last one without an index
        dom = self._test_parse_build(
            "\x01a\x01b\x01c",
            """
                typedef struct {
                    uchar length;
                    char str[length];
                } STR;

                local int total_length = 0;
                while(!FEof()) {
                    STR str;
                    total_length += str.length;
                }
                Printf("%d", total_length);
            """,
            stdout="3",
        )

if __name__ == "__main__":
    unittest.main()
<commit_msg>Need to work on parameterized structs some more, probably py010parser work<commit_after>#!/usr/bin/env python
# encoding: utf-8

import os
import sys
import unittest

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

import pfp
import pfp.fields
import pfp.interp
import pfp.utils

import utils

class TestStructUnion(utils.PfpTestCase):
    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_struct_vit9696_1(self):
        dom = self._test_parse_build(
            "\x00\x01\x02\x03\x00\x01\x02\x03",
            """
                typedef struct MY_STRUCT_S {
                    char magic[4];
                    unsigned int filesize;
                } MY_STRUCT;
                LittleEndian();
                MY_STRUCT s;
            """
        )
        assert dom.s.magic == "\x00\x01\x02\x03"
        assert dom.s.filesize == 0x03020100

    def test_struct_vit9696_2(self):
        dom = self._test_parse_build(
            "\x00\x01\x02\x03\x00\x01\x02\x03",
            """
                struct MY_STRUCT {
                    char magic[4];
                    unsigned int filesize;
                };
                LittleEndian();
                MY_STRUCT s;
            """
        )
        assert dom.s.magic == "\x00\x01\x02\x03"
        assert dom.s.filesize == 0x03020100

    def test_struct_vit9696_3(self):
        dom = self._test_parse_build(
            "\x00\x01\x02\x03\x00\x01\x02\x03",
            """
                typedef struct MY_STRUCT {
                    char magic[4];
                    unsigned int filesize;
                };
                LittleEndian();
                MY_STRUCT s;
            """
        )
        assert dom.s.magic == "\x00\x01\x02\x03"
        assert dom.s.filesize == 0x03020100

    def test_struct_vit9696_4(self):
        dom = self._test_parse_build(
            "\x00\x01\x02\x03\x00\x01\x02\x03",
            """
                struct MY_STRUCT {
                    char magic[4];
                    unsigned int filesize;
                };
                LittleEndian();
                struct MY_STRUCT s;
            """
        )
        assert dom.s.magic == "\x00\x01\x02\x03"
        assert dom.s.filesize == 0x03020100

    def test_struct_vit9696_5(self):
        dom = self._test_parse_build(
            "\x00\x01\x02\x03\x00\x01\x02\x03",
            """
                struct MY_STRUCT {
                    char magic[4];
                    unsigned int filesize;
                };
                typedef struct MY_STRUCT ME;
                LittleEndian();
                ME s;
            """,
            debug=True,
        )
        assert dom.s.magic == "\x00\x01\x02\x03"
        assert dom.s.filesize == 0x03020100

    def test_basic_struct(self):
        dom = self._test_parse_build(
            "\x00\x01\x02\x03",
            """
                struct SomeStruct {
                    byte a;
                    byte b;
                    byte c;
                    byte d;
                };
                struct SomeStruct test;
            """
        )
        assert dom.test.a == 0
        assert dom.test.b == 1
        assert dom.test.c == 2
        assert dom.test.d == 3

    def test_field_path(self):
        dom = self._test_parse_build(
            "Abbbb4141414142424242",
            """
                struct {
                    struct {
                        struct {
                            char inner;
                            char array[4];
                        } nested2;
                        int some_int;
                    } nested1;
                    int some_int2;
                } root;
            """,
        )
        self.assertEqual(dom.root._pfp__path(), "root")
        self.assertEqual(dom.root.some_int2._pfp__path(), "root.some_int2")
        self.assertEqual(dom.root.nested1._pfp__path(), "root.nested1")
        self.assertEqual(dom.root.nested1.some_int._pfp__path(), "root.nested1.some_int")
        self.assertEqual(dom.root.nested1.nested2._pfp__path(), "root.nested1.nested2")
        self.assertEqual(dom.root.nested1.nested2.inner._pfp__path(), "root.nested1.nested2.inner")
        self.assertEqual(dom.root.nested1.nested2.array._pfp__path(), "root.nested1.nested2.array")
        self.assertEqual(dom.root.nested1.nested2.array[0]._pfp__path(), "root.nested1.nested2.array[0]")
        self.assertEqual(dom.root.nested1.nested2.array[1]._pfp__path(), "root.nested1.nested2.array[1]")
        self.assertEqual(dom.root.nested1.nested2.array[2]._pfp__path(), "root.nested1.nested2.array[2]")
        self.assertEqual(dom.root.nested1.nested2.array[3]._pfp__path(), "root.nested1.nested2.array[3]")

    def test_struct(self):
        dom = self._test_parse_build(
            "abcddcba",
            """
                typedef struct {
                    int some_int;
                } blah;

                blah some_struct;
                blah some_struct2;
            """,
        )

    def test_forward_declared_struct(self):
        dom = self._test_parse_build(
            "\x00\x01",
            """
                struct fp16;
                void ReadFP16(fp16& f)
                {
                    Printf("%d", f.value);
                }
                typedef struct
                {
                    int16 value;
                } fp16;
                fp16 preferred_volume;
                ReadFP16(preferred_volume);
            """,
            stdout="256",
        )

    def test_struct_with_parameters(self):
        dom = self._test_parse_build(
            "aabbb",
            """
                typedef struct (int a, int b) {
                    char chars1[a];
                    char chars2[b];
                } blah;

                blah test(2, 3);
            """,
        )
        self.assertEqual(dom.test.chars1, "aa")
        self.assertEqual(dom.test.chars2, "bbb")

    def test_struct_with_parameters2(self):
        # ``descr_length l(bytes)`` is being treated as a function
        # declaration!
        dom = self._test_parse_build(
            "\x01\x02\x03\x04",
            """
                typedef struct (int arraySize)
                {
                    uchar b[arraySize];
                } descr_length <read=descr_format>;

                local int bytes = 4;
                descr_length l(bytes);
            """,
        )
        self.assertEqual(len(dom.l.b), 4)
        self.assertEqual(dom.l.b[0], 1)
        self.assertEqual(dom.l.b[1], 2)
        self.assertEqual(dom.l.b[2], 3)
        self.assertEqual(dom.l.b[3], 4)

    def test_struct_with_parameters3(self):
        # ``descr_length l(bytes)`` is being treated as a function
        # declaration!
        dom = self._test_parse_build(
            "\x01\x02\x03\x04\x01\x02\x03",
            """
                typedef struct (int arraySize, int arraySize2)
                {
                    uchar b[arraySize];
                    uchar c[arraySize2];
                } descr_length <read=descr_format>;

                local int bytes = 4;
                descr_length l(bytes, 3);
            """,
        )
        self.assertEqual(len(dom.l.b), 4)
        self.assertEqual(dom.l.b[0], 1)
        self.assertEqual(dom.l.b[1], 2)
        self.assertEqual(dom.l.b[2], 3)
        self.assertEqual(dom.l.b[3], 4)
        self.assertEqual(len(dom.l.c), 3)
        self.assertEqual(dom.l.c[0], 1)
        self.assertEqual(dom.l.c[1], 2)
        self.assertEqual(dom.l.c[2], 3)

    def test_typedefd_struct_with_parameters(self):
        # ``descr_length l(bytes)`` is being treated as a function
        # declaration!
        dom = self._test_parse_build(
            "\x01\x02\x03\x04\x01\x02\x03",
            """
                struct TEST_STRUCT(int arraySize, int arraySize2)
                {
                    uchar b[arraySize];
                    uchar c[arraySize2];
                };
                local int bytes = 4;
                typedef struct TEST_STRUCT NEW_STRUCT;
                NEW_STRUCT l(bytes, 3);
            """,
        )
        self.assertEqual(len(dom.l.b), 4)
        self.assertEqual(dom.l.b[0], 1)
        self.assertEqual(dom.l.b[1], 2)
        self.assertEqual(dom.l.b[2], 3)
        self.assertEqual(dom.l.b[3], 4)
        self.assertEqual(len(dom.l.c), 3)
        self.assertEqual(dom.l.c[0], 1)
        self.assertEqual(dom.l.c[1], 2)
        self.assertEqual(dom.l.c[2], 3)

    def test_struct_decl_with_struct_keyword(self):
        dom = self._test_parse_build(
            "ABCD",
            """
                typedef struct {
                    char a;
                    char b;
                    char c;
                    char d;
                } BLAH;

                struct BLAH decldStruct;
            """,
        )

        self.assertEqual(dom.decldStruct.a, ord("A"))
        self.assertEqual(dom.decldStruct.b, ord("B"))
        self.assertEqual(dom.decldStruct.c, ord("C"))
        self.assertEqual(dom.decldStruct.d, ord("D"))

    def test_struct_initialization(self):
        # local structs aren't allowed!!!
        return

    #        dom = self._test_parse_build(
    #            "",
    #            """
    #                typedef struct {
    #                    char a;
    #                    char b;
    #                    char c;
    #                    char d;
    #                } blah;
    #
    #                local blah some_struct = { 'a', 'b', 'c', 'd'};
    #            """
    #        )

    def test_union(self):
        dom = self._test_parse_build(
            "abcd",
            """
                typedef union {
                    int some_int;
                    struct {
                        char a;
                        char b;
                        char c;
                        char d;
                    } some_chars;
                } blah;

                blah some_union;
            """,
        )

    def test_union_complex(self):
        dom = self._test_parse_build(
            "\x00abcd",
            """
                typedef struct {
                    uchar a;
                    uchar b;
                    uchar c;
                    uchar d;
                } TEST;

                struct {
                    uchar blah;
                    union {
                        TEST chars;
                        uchar raw[sizeof(chars)];
                    } onion;
                } test;
            """,
        )
        self.assertEqual(dom.test.onion.raw, "abcd")
        self.assertEqual(dom.test.onion.chars.a, ord("a"))
        self.assertEqual(dom.test.onion.chars.b, ord("b"))
        self.assertEqual(dom.test.onion.chars.c, ord("c"))
        self.assertEqual(dom.test.onion.chars.d, ord("d"))

    def test_union_offset1(self):
        dom = self._test_parse_build(
            "abcd",
            """
                struct {
                    char a;
                    char b;
                    union {
                        char c;
                        uchar uc;
                    } union_test;
                    char d;
                } test;
            """,
        )
        self.assertEqual(dom.test.union_test._pfp__offset, 2)

    def test_union_offset2(self):
        dom = self._test_parse_build(
            "abcd",
            """
                typedef union {
                    char c;
                    uchar uc;
                } CHAR_UNION;

                struct {
                    char a;
                    char b;
                    CHAR_UNION union_test;
                    char d;
                } test;
            """,
        )
        self.assertEqual(dom.test.union_test._pfp__offset, 2)

    def test_auto_increment_field_names(self):
        # when a field is declared multiple times with the same name, but
        # not consecutively, the fields should get a sequential number assigned
        # to them and NOT be stored in an implicit array
        dom = self._test_parse_build(
            "a\x00\x010\x00\x02",
            """
                BigEndian();
                while(!FEof()) {
                    char header;
                    short val;
                }
            """,
        )

        self.assertEqual(dom.header_0, ord("a"))
        self.assertEqual(dom.val_0, 1)

        self.assertEqual(dom.header_1, ord("0"))
        self.assertEqual(dom.val_1, 2)

    def test_auto_increment_but_still_reference_last_decl_normal(self):
        # this is an interesting behavior of 010 scripts. When a field
        # is repeatedly declared, 010 scripts do not append a suffix to
        # the field names. However, since our goal is manipulation and being
        # able to access these fields individually, we do add a suffix.
        # the problem is that the script still needs to be able to access
        # the last declared field by the original name and not the
        # suffixed one.
        dom = self._test_parse_build(
            "\x01a\x01b\x01c",
            """
                while(!FEof()) {
                    char length;
                    char str[length];
                    Printf("%s|", str);
                }
            """,
            stdout="a|b|c|",
        )

    def test_implicit_array_dot_notation_for_last(self):
        # I BELIEVE scripts are able to access implicit array items
        # by index OR directly access the last one without an index
        dom = self._test_parse_build(
            "\x01a\x01b\x01c",
            """
                typedef struct {
                    uchar length;
                    char str[length];
                } STR;

                local int total_length = 0;
                while(!FEof()) {
                    STR str;
                    total_length += str.length;
                }
                Printf("%d", total_length);
            """,
            stdout="3",
        )

if __name__ == "__main__":
    unittest.main()
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import mapnik
import sys
import os.path
from compare import compare, summary

defaults = {
    'sizes': [(500, 100)],
    'bbox': mapnik.Box2d(-0.05, -0.01, 0.95, 0.01)
}

sizes_many_in_big_range = [(800, 100), (600, 100), (400, 100),
    (300, 100), (250, 100), (150, 100), (100, 100)]

sizes_few_square = [(800, 800), (600, 600), (400, 400), (200, 200)]
sizes_many_in_small_range = [(490, 100), (495, 100), (497, 100), (498, 100),
    (499, 100), (500, 100), (501, 100), (502, 100), (505, 100), (510, 100)]

dirname = os.path.dirname(__file__)

files = [
    {'name': "list", 'sizes': sizes_many_in_big_range},
    {'name': "simple", 'sizes': sizes_many_in_big_range},
    {'name': "lines-1", 'sizes': sizes_few_square},
    {'name': "lines-2", 'sizes': sizes_few_square},
    {'name': "lines-3", 'sizes': sizes_few_square},
    {'name': "lines-shield", 'sizes': sizes_few_square},
    {'name': "simple-E"},
    {'name': "simple-NE"},
    {'name': "simple-NW"},
    {'name': "simple-N"},
    {'name': "simple-SE"},
    {'name': "simple-SW"},
    {'name': "simple-S"},
    {'name': "simple-W"},
    {'name': "formatting-1"},
    {'name': "formatting-2"},
    {'name': "formatting-3"},
    {'name': "formatting-4"},
    {'name': "expressionformat"},
    {'name': "shieldsymbolizer-1", 'sizes': sizes_many_in_small_range},
    {'name': "rtl-point", 'sizes': [(200, 200)]},
    {'name': "jalign-auto", 'sizes': [(200, 200)]},
    {'name': "line-offset", 'sizes':[(900, 250)],
        'bbox': mapnik.Box2d(-5.192, 50.189, -5.174, 50.195)}
    ]

def render(filename, width, height, bbox, quiet=False):
    if not quiet:
        print "Rendering style \"%s\" with size %dx%d ... \x1b[1;32m✓ \x1b[0m" % (filename, width, height)
        print "-"*80
    m = mapnik.Map(width, height)
    mapnik.load_map(m, os.path.join(dirname, "styles", "%s.xml" % filename), False)
    if bbox is not None:
        m.zoom_to_box(bbox)
    else:
        m.zoom_all()
    expected = os.path.join(dirname, "images", '%s-%d-reference.png' % (filename, width))
    if not os.path.exists('/tmp/mapnik-visual-images'):
        os.makedirs('/tmp/mapnik-visual-images')
    actual = os.path.join("/tmp/mapnik-visual-images", '%s-%d-agg.png' % (filename, width))
    mapnik.render_to_file(m, actual)
    diff = compare(actual, expected)
    if diff > 0:
        print "-"*80
        print '\x1b[33mError:\x1b[0m %u different pixels' % diff
        print "-"*80

    return m

if __name__ == "__main__":
    if '-q' in sys.argv:
       quiet = True
       sys.argv.remove('-q')
    else:
       quiet = False

    if len(sys.argv) == 2:
        files = [(sys.argv[1], (500, 500))]
    elif len(sys.argv) > 2:
        files = [sys.argv[1:]]

    for f in files:
        config = dict(defaults)
        config.update(f)
        for size in config['sizes']:
            m = render(config['name'], size[0], size[1], config['bbox'], quiet=quiet)
        mapnik.save_map(m, os.path.join(dirname, 'xml_output', "%s-out.xml" % config['name']))

    summary()
<commit_msg>Fix visual_tests/test.py.<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import mapnik
import sys
import os.path
from compare import compare, summary

defaults = {
    'sizes': [(500, 100)],
    'bbox': mapnik.Box2d(-0.05, -0.01, 0.95, 0.01)
}

sizes_many_in_big_range = [(800, 100), (600, 100), (400, 100),
    (300, 100), (250, 100), (150, 100), (100, 100)]

sizes_few_square = [(800, 800), (600, 600), (400, 400), (200, 200)]
sizes_many_in_small_range = [(490, 100), (495, 100), (497, 100), (498, 100),
    (499, 100), (500, 100), (501, 100), (502, 100), (505, 100), (510, 100)]

dirname = os.path.dirname(__file__)

files = [
    {'name': "list", 'sizes': sizes_many_in_big_range},
    {'name': "simple", 'sizes': sizes_many_in_big_range},
    {'name': "lines-1", 'sizes': sizes_few_square},
    {'name': "lines-2", 'sizes': sizes_few_square},
    {'name': "lines-3", 'sizes': sizes_few_square},
    {'name': "lines-shield", 'sizes': sizes_few_square},
    {'name': "simple-E"},
    {'name': "simple-NE"},
    {'name': "simple-NW"},
    {'name': "simple-N"},
    {'name': "simple-SE"},
    {'name': "simple-SW"},
    {'name': "simple-S"},
    {'name': "simple-W"},
    {'name': "formatting-1"},
    {'name': "formatting-2"},
    {'name': "formatting-3"},
    {'name': "formatting-4"},
    {'name': "expressionformat"},
    {'name': "shieldsymbolizer-1", 'sizes': sizes_many_in_small_range},
    {'name': "rtl-point", 'sizes': [(200, 200)]},
    {'name': "jalign-auto", 'sizes': [(200, 200)]},
    {'name': "line-offset", 'sizes':[(900, 250)],
        'bbox': mapnik.Box2d(-5.192, 50.189, -5.174, 50.195)},
    ]

def render(filename, width, height, bbox, quiet=False):
    if not quiet:
        print "Rendering style \"%s\" with size %dx%d ... \x1b[1;32m✓ \x1b[0m" % (filename, width, height)
        print "-"*80
    m = mapnik.Map(width, height)
    mapnik.load_map(m, os.path.join(dirname, "styles", "%s.xml" % filename), False)
    if bbox is not None:
        m.zoom_to_box(bbox)
    else:
        m.zoom_all()
    expected = os.path.join(dirname, "images", '%s-%d-reference.png' % (filename, width))
    if not os.path.exists('/tmp/mapnik-visual-images'):
        os.makedirs('/tmp/mapnik-visual-images')
    actual = os.path.join("/tmp/mapnik-visual-images", '%s-%d-agg.png' % (filename, width))
    mapnik.render_to_file(m, actual)
    diff = compare(actual, expected)
    if diff > 0:
        print "-"*80
        print '\x1b[33mError:\x1b[0m %u different pixels' % diff
        print "-"*80

    return m

if __name__ == "__main__":
    if '-q' in sys.argv:
       quiet = True
       sys.argv.remove('-q')
    else:
       quiet = False

    if len(sys.argv) == 2:
        files = [{"name": sys.argv[1], "sizes": sizes_few_square}]
    elif len(sys.argv) > 2:
        files = []
        for name in argv[1:]:
            files.append({"name": name})

    for f in files:
        config = dict(defaults)
        config.update(f)
        for size in config['sizes']:
            m = render(config['name'], size[0], size[1], config['bbox'], quiet=quiet)
        mapnik.save_map(m, os.path.join(dirname, 'xml_output', "%s-out.xml" % config['name']))

    summary()
<|endoftext|>


<commit_before>import re
from l20n import ast

class ParserError(Exception):
    pass

class Parser():
    patterns = {
        'id': re.compile('^([a-zA-Z]\w*)'),
        'value': re.compile('^(?P<op>[\'"])(.*?)(?<!\\\)(?P=op)'),
    }

    def parse(self, content):
        lol = ast.LOL()
        lol._struct = True
        lol._template = []
        self.content = content
        lol._template.append(self.get_ws())
        while self.content:
            try:
                lol.body.append(self.get_entry())
            except IndexError:
                raise ParserError()
            lol._template.append(self.get_ws())
        return lol

    def get_ws(self):
        content = self.content.lstrip()
        ws = self.content[:len(content)*-1]
        self.content = content
        return ws

    def get_entry(self):
        if self.content[0] == '<':
            self.content = self.content[1:]
            id = self.get_identifier()
            if self.content[0] == '(':
                entry = self.get_macro(id)
            elif self.content[0] == '[':
                index = self.get_index()
                entry = self.get_entity(id, index)
            else:
                entry = self.get_entity(id)
        elif self.content[0:2] == '/*':
            entry = self.get_comment(self.ptr)
        else:
            raise ParserError()
        return entry

    def get_identifier(self):
        match = self.patterns['id'].match(self.content)
        if not match:
            raise ParserError()
        self.content = self.content[match.end(0):]
        return ast.Identifier(match.group(1))

    def get_entity(self, id, index=None):
        ws1 = self.get_ws()
        if self.content[0] == '>':
            self.content = self.content[1:]
            entity = ast.Entity(id)
            entity._template = "<%%s%s>" % ws1
            return entity
        if len(ws1) == 0:
            raise ParserError()
        value = self.get_value(none=True)
        ws2 = self.get_ws()
        attrs = self.get_attributes()
        entity = ast.Entity(id,
                            index,
                            value,
                            attrs)
        entity._template = "<%%s%%s%s%%s%s%%s>" % (ws1,ws2)
        return entity

    def get_macro(self, id):
        idlist = []
        self.content = self.content[1:]
        self.get_ws()
        while self.content[0] != ')':
            idlist.append(self.get_identifier())
            self.get_ws()
            if self.content[0] == ',':
                self.content = self.content[1:]
                self.get_ws()
        self.content = self.content[1:]
        ws = self.get_ws()
        if len(ws) == 0:
            raise ParserError()
        if self.content[0] != '{':
            raise ParserError()
        self.content = self.content[1:]
        exp = self.get_expression()
        self.get_ws()
        if self.content[0] != '}':
            raise ParserError()
        self.content = self.content[1:]
        attrs = self.get_attributes()
        return ast.Macro(id,
                         idlist,
                         exp,
                         attrs)

    def get_value(self, none=False):
        c = self.content[0]
        if c in ('"', "'"):
            value = self.get_string()
        elif c == '[':
            value = self.get_array()
        elif c == '{':
            value = self.get_hash()
        else:
            if none is True:
                return None
            raise ParserError()
        return value

    def get_string(self):
        match = self.patterns['value'].match(self.content)
        if not match:
            raise ParserError()
        self.content = self.content[match.end(0):]
        return ast.String(match.group(2))

    def get_array(self):
        self.content = self.content[1:]
        array = []
        ws = self.get_ws()
        while self.content[0] != ']':
            array.append(self.get_value())
            ws = self.get_ws()
            if self.content[0] == ',':
                self.content = self.content[1:]
                ws2 = self.get_ws()
        self.content = self.content[1:]
        return ast.Array(array)

    def get_hash(self):
        hash = []
        self.content = self.content[1:]
        ws = self.get_ws()
        while self.content[0] != '}':
            kvp = self.get_kvp()
            hash.append(kvp)
            ws = self.get_ws()
            if self.content[0] == ',':
                self.content = self.content[1:]
                ws2 = self.get_ws()
        self.content = self.content[1:]
        return ast.Hash(hash)

    def get_kvp(self):
        ws = self.get_ws()
        key = self.get_identifier()
        ws2 = self.get_ws()
        if self.content[0] != ':':
            raise ParserError()
        self.content = self.content[1:]
        ws3 = self.get_ws()
        val = self.get_value()
        return ast.KeyValuePair(key, val)

    def get_attributes(self):
        hash = []
        while self.content[0] != '>':
            ws = self.get_ws()
            kvp = self.get_kvp()
            hash.append(kvp)
            ws2 = self.get_ws()
        self.content = self.content[1:]
        return hash if len(hash) else None

    def get_index(self):
        index = []
        self.content = self.content[1:]
        ws = self.get_ws()
        while self.content[0] != ']':
            expression = self.get_expression()
            index.append(expression)
            ws = self.get_ws()
            if self.content[0] == ',':
                self.content = self.content[1:]
                self.get_ws()
        self.content = self.content[1:]
        return index

    def get_expression(self):
        return self.get_conditional_expression()

    def get_conditional_expression(self):
        or_expression = self.get_or_expression()
        self.get_ws()
        if self.content[0] != '?':
            return or_expression
        self.content = self.content[1:]
        self.get_ws()
        consequent = self.get_expression()
        self.get_ws()
        if self.content[0] != ':':
            raise ParserError()
        self.content = self.content[1:]
        self.get_ws()
        alternate = self.get_expression()
        self.get_ws()
        return ast.ConditionalExpression(or_expression,
                                         consequent,
                                         alternate)

    def get_prefix_expression(self, token, token_length, cl, op, nxt):
        exp = nxt()
        self.get_ws()
        while self.content[:token_length] in token:
            t = self.content[:token_length]
            self.content = self.content[token_length:]
            self.get_ws()
            exp = cl(op(t),
                     exp,
                     nxt())
            self.get_ws()
        return exp

    def get_prefix_expression_re(self, token, cl, op, nxt):
        exp = nxt()
        self.get_ws()
        m = token.match(self.content)
        while m:
            self.content = self.content[m.end(0):]
            self.get_ws()
            exp = cl(op(m.group(0)),
                     exp,
                     nxt())
            self.get_ws()
            m = token.match(self.content)
        return exp

    def get_postfix_expression(self, token, token_length, cl, op, nxt):
        t = self.content[0]
        if t not in token:
            return nxt()
        self.content = self.content[1:]
        self.get_ws()
        return cl(op(t),
                  self.get_postfix_expression())

    def get_or_expression(self,
                          token=('||',),
                          cl=ast.LogicalExpression,
                          op=ast.LogicalOperator):
        self.get_prefix_expression(token, 2, cl, op, self.get_and_expression)

    def get_and_expression(self,
                          token=('&&',),
                          cl=ast.LogicalExpression,
                          op=ast.LogicalOperator):
        self.get_prefix_expression(token, 2, cl, op, self.get_equality_expression)

    def get_equality_expression(self,
                          token=('==', '!='),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        self.get_prefix_expression(token, 2, cl, op, self.get_relational_expression)

    def get_relational_expression(self,
                          token=re.compile('^[<>]=?'),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        self.get_prefix_expression_re(token, cl, op, self.get_additive_expression)

    def get_additive_expression(self,
                          token=('+', '-'),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        self.get_prefix_expression(token, 1, cl, op, self.get_multiplicative_expression)

    def get_multiplicative_expression(self,
                          token=('*',),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        self.get_prefix_expression(token, 1, cl, op, self.get_dividive_expression)

    def get_dividive_expression(self,
                          token=('/',),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        self.get_prefix_expression(token, 1, cl, op, self.get_modulo_expression)

    def get_modulo_expression(self,
                          token=('%',),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        self.get_prefix_expression(token, 1, cl, op, self.get_unary_expression)

    def get_unary_expression(self,
                          token=('+', '-', '!'),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        self.get_postfix_expression(token, 1, cl, op, self.get_primary_expression)

    def get_primary_expression(self):
        if self.content[0] == "(":
            self.content = self.content[1:]
            ws = self.get_ws()
            pexp = ast.ParenthesisExpression(self.get_expression())
            ws = self.get_ws()
            if self.content[0] != ')':
                raise ParserError()
            self.content = self.content[1:]
            return pexp
        #number
        ptr = 0
        while self.content[ptr].isdigit():
            ptr+=1
        if ptr:
            d =  int(self.content[:ptr])
            self.content = self.content[ptr:]
            return ast.Literal(d)
        #value
        if self.content[0] in ('"\'{['):
            return self.get_value()
        #idref (with index?) or macrocall
        idref = self.get_identifier()
        if self.content[0:2] == '[.':
            return self.get_attr_expression(idref)
        elif self.content[0] == '[':
            return self.get_member_expression(idref)
        elif self.content[0] != '(':
            return idref
        #macro
        mcall = ast.CallExpression(idref)
        self.content = self.content[1:]
        self.get_ws()
        while self.content[0] != ')':
            exp = self.get_expression()
            mcall.arguments.append(exp)
            self.get_ws()
            if self.content[0] == ',':
                self.content = self.content[1:]
                self.get_ws()
        self.content = self.content[1:]
        return mcall

    def get_attr_expression(self, idref):
        self.content = self.content[2:]
        self.get_ws()
        exp = self.get_expression()
        self.get_ws()
        self.content = self.content[1:]
        return ast.AttributeExpression(idref, exp)

    def get_member_expression(self, idref):
        self.content = self.content[1:]
        self.get_ws()
        exp = self.get_expression()
        self.get_ws()
        self.content = self.content[1:]
        return ast.MemberExpression(idref, exp)

<commit_msg>clean up expression parsing to pass tests<commit_after>import re
from l20n import ast

class ParserError(Exception):
    pass

class Parser():
    patterns = {
        'id': re.compile('^([a-zA-Z]\w*)'),
        'value': re.compile('^(?P<op>[\'"])(.*?)(?<!\\\)(?P=op)'),
    }

    def parse(self, content):
        lol = ast.LOL()
        lol._struct = True
        lol._template = []
        self.content = content
        lol._template.append(self.get_ws())
        while self.content:
            try:
                lol.body.append(self.get_entry())
            except IndexError:
                raise ParserError()
            lol._template.append(self.get_ws())
        return lol

    def get_ws(self):
        content = self.content.lstrip()
        ws = self.content[:len(content)*-1]
        self.content = content
        return ws

    def get_entry(self):
        if self.content[0] == '<':
            self.content = self.content[1:]
            id = self.get_identifier()
            if self.content[0] == '(':
                entry = self.get_macro(id)
            elif self.content[0] == '[':
                index = self.get_index()
                entry = self.get_entity(id, index)
            else:
                entry = self.get_entity(id)
        elif self.content[0:2] == '/*':
            entry = self.get_comment(self.ptr)
        else:
            raise ParserError()
        return entry

    def get_identifier(self):
        match = self.patterns['id'].match(self.content)
        if not match:
            raise ParserError()
        self.content = self.content[match.end(0):]
        return ast.Identifier(match.group(1))

    def get_entity(self, id, index=None):
        ws1 = self.get_ws()
        if self.content[0] == '>':
            self.content = self.content[1:]
            entity = ast.Entity(id)
            entity._template = "<%%s%s>" % ws1
            return entity
        if len(ws1) == 0:
            raise ParserError()
        value = self.get_value(none=True)
        ws2 = self.get_ws()
        attrs = self.get_attributes()
        entity = ast.Entity(id,
                            index,
                            value,
                            attrs)
        entity._template = "<%%s%%s%s%%s%s%%s>" % (ws1,ws2)
        return entity

    def get_macro(self, id):
        idlist = []
        self.content = self.content[1:]
        self.get_ws()
        while self.content[0] != ')':
            idlist.append(self.get_identifier())
            self.get_ws()
            if self.content[0] == ',':
                self.content = self.content[1:]
                self.get_ws()
        self.content = self.content[1:]
        ws = self.get_ws()
        if len(ws) == 0:
            raise ParserError()
        if self.content[0] != '{':
            raise ParserError()
        self.content = self.content[1:]
        exp = self.get_expression()
        self.get_ws()
        if self.content[0] != '}':
            raise ParserError()
        self.content = self.content[1:]
        attrs = self.get_attributes()
        return ast.Macro(id,
                         idlist,
                         exp,
                         attrs)

    def get_value(self, none=False):
        c = self.content[0]
        if c in ('"', "'"):
            value = self.get_string()
        elif c == '[':
            value = self.get_array()
        elif c == '{':
            value = self.get_hash()
        else:
            if none is True:
                return None
            raise ParserError()
        return value

    def get_string(self):
        match = self.patterns['value'].match(self.content)
        if not match:
            raise ParserError()
        self.content = self.content[match.end(0):]
        return ast.String(match.group(2))

    def get_array(self):
        self.content = self.content[1:]
        array = []
        ws = self.get_ws()
        while self.content[0] != ']':
            array.append(self.get_value())
            ws = self.get_ws()
            if self.content[0] == ',':
                self.content = self.content[1:]
                ws2 = self.get_ws()
        self.content = self.content[1:]
        return ast.Array(array)

    def get_hash(self):
        hash = []
        self.content = self.content[1:]
        ws = self.get_ws()
        while self.content[0] != '}':
            kvp = self.get_kvp()
            hash.append(kvp)
            ws = self.get_ws()
            if self.content[0] == ',':
                self.content = self.content[1:]
                ws2 = self.get_ws()
        self.content = self.content[1:]
        return ast.Hash(hash)

    def get_kvp(self):
        ws = self.get_ws()
        key = self.get_identifier()
        ws2 = self.get_ws()
        if self.content[0] != ':':
            raise ParserError()
        self.content = self.content[1:]
        ws3 = self.get_ws()
        val = self.get_value()
        return ast.KeyValuePair(key, val)

    def get_attributes(self):
        hash = []
        while self.content[0] != '>':
            ws = self.get_ws()
            kvp = self.get_kvp()
            hash.append(kvp)
            ws2 = self.get_ws()
        self.content = self.content[1:]
        return hash if len(hash) else None

    def get_index(self):
        index = []
        self.content = self.content[1:]
        ws = self.get_ws()
        while self.content[0] != ']':
            expression = self.get_expression()
            index.append(expression)
            ws = self.get_ws()
            if self.content[0] == ',':
                self.content = self.content[1:]
                self.get_ws()
        self.content = self.content[1:]
        return index

    def get_expression(self):
        return self.get_conditional_expression()

    def get_conditional_expression(self):
        or_expression = self.get_or_expression()
        self.get_ws()
        if self.content[0] != '?':
            return or_expression
        self.content = self.content[1:]
        self.get_ws()
        consequent = self.get_expression()
        self.get_ws()
        if self.content[0] != ':':
            raise ParserError()
        self.content = self.content[1:]
        self.get_ws()
        alternate = self.get_expression()
        self.get_ws()
        return ast.ConditionalExpression(or_expression,
                                         consequent,
                                         alternate)

    def get_prefix_expression(self, token, token_length, cl, op, nxt):
        exp = nxt()
        self.get_ws()
        while self.content[:token_length] in token:
            t = self.content[:token_length]
            self.content = self.content[token_length:]
            self.get_ws()
            exp = cl(op(t),
                     exp,
                     nxt())
            self.get_ws()
        return exp

    def get_prefix_expression_re(self, token, cl, op, nxt):
        exp = nxt()
        self.get_ws()
        m = token.match(self.content)
        while m:
            self.content = self.content[m.end(0):]
            self.get_ws()
            exp = cl(op(m.group(0)),
                     exp,
                     nxt())
            self.get_ws()
            m = token.match(self.content)
        return exp

    def get_postfix_expression(self, token, token_length, cl, op, nxt):
        t = self.content[0]
        if t not in token:
            return nxt()
        self.content = self.content[1:]
        self.get_ws()
        return cl(op(t),
                  self.get_postfix_expression(token, token_length, cl, op, nxt))

    def get_or_expression(self,
                          token=('||',),
                          cl=ast.LogicalExpression,
                          op=ast.LogicalOperator):
        return self.get_prefix_expression(token, 2, cl, op, self.get_and_expression)

    def get_and_expression(self,
                          token=('&&',),
                          cl=ast.LogicalExpression,
                          op=ast.LogicalOperator):
        return self.get_prefix_expression(token, 2, cl, op, self.get_equality_expression)

    def get_equality_expression(self,
                          token=('==', '!='),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        return self.get_prefix_expression(token, 2, cl, op, self.get_relational_expression)

    def get_relational_expression(self,
                          token=re.compile('^[<>]=?'),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        return self.get_prefix_expression_re(token, cl, op, self.get_additive_expression)

    def get_additive_expression(self,
                          token=('+', '-'),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        return self.get_prefix_expression(token, 1, cl, op, self.get_multiplicative_expression)

    def get_multiplicative_expression(self,
                          token=('*',),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        return self.get_prefix_expression(token, 1, cl, op, self.get_dividive_expression)

    def get_dividive_expression(self,
                          token=('/',),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        return self.get_prefix_expression(token, 1, cl, op, self.get_modulo_expression)

    def get_modulo_expression(self,
                          token=('%',),
                          cl=ast.BinaryExpression,
                          op=ast.BinaryOperator):
        return self.get_prefix_expression(token, 1, cl, op, self.get_unary_expression)

    def get_unary_expression(self,
                          token=('+', '-', '!'),
                          cl=ast.UnaryExpression,
                          op=ast.UnaryOperator):
        return self.get_postfix_expression(token, 1, cl, op, self.get_primary_expression)

    def get_primary_expression(self):
        if self.content[0] == "(":
            self.content = self.content[1:]
            ws = self.get_ws()
            pexp = ast.ParenthesisExpression(self.get_expression())
            ws = self.get_ws()
            if self.content[0] != ')':
                raise ParserError()
            self.content = self.content[1:]
            return pexp
        #number
        ptr = 0
        while self.content[ptr].isdigit():
            ptr+=1
        if ptr:
            d =  int(self.content[:ptr])
            self.content = self.content[ptr:]
            return ast.Literal(d)
        #value
        if self.content[0] in ('"\'{['):
            return self.get_value()
        #idref (with index?) or macrocall
        idref = self.get_identifier()
        if self.content[0:2] == '[.':
            return self.get_attr_expression(idref)
        elif self.content[0] == '[':
            return self.get_member_expression(idref)
        elif self.content[0] != '(':
            return idref
        #macro
        mcall = ast.CallExpression(idref)
        self.content = self.content[1:]
        self.get_ws()
        while self.content[0] != ')':
            exp = self.get_expression()
            mcall.arguments.append(exp)
            self.get_ws()
            if self.content[0] == ',':
                self.content = self.content[1:]
                self.get_ws()
        self.content = self.content[1:]
        return mcall

    def get_attr_expression(self, idref):
        self.content = self.content[2:]
        self.get_ws()
        exp = self.get_expression()
        self.get_ws()
        self.content = self.content[1:]
        return ast.AttributeExpression(idref, exp)

    def get_member_expression(self, idref):
        self.content = self.content[1:]
        self.get_ws()
        exp = self.get_expression()
        self.get_ws()
        self.content = self.content[1:]
        return ast.MemberExpression(idref, exp)

<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    import config
    verbose = config.verbose
    test_mode = config.test_mode
    pin_numbering = config.pin_numbering
    config_path = config.config_path
except:
    raise ValueError('Error loading configuration.')

if verbose:
    import version
    print('L293D driver version ' + version.num)

from time import sleep
from threading import Thread

try:
    import RPi.GPIO as GPIO
except Exception as e:
    print("Can't import RPi.GPIO. Please (re)install.")
    test_mode = True
    print('Test mode has been enabled. Please view README for more info.')

if not test_mode:
    try:
        GPIO.setmode(GPIO.BOARD)
        GPIO.setwarnings(False)
        if verbose: print('GPIO mode set (GPIO.BOARD)')
    except Exception as e:
        print('Can\'t set GPIO mode (GPIO.BOARD)')

pins_in_use = [] # Lists pins in use (all motors)

class motor(object):
    """
    A motor wired to the L293D chip where
    motor_pins[0] is pinA is L293D pin1 or pin9  : On or off
    motor_pins[1] is pinB is L293D pin2 or pin10 : Anticlockwise positive
    motor_pins[2] is pinC is L293D pin7 or pin15 : Clockwise positive
    """

    motor_pins = [0 for x in range(3)]

    def __init__(self, pinA=0, pinB=0, pinC=0):
        self.motor_pins[0] = pinA
        self.motor_pins[1] = pinB
        self.motor_pins[2] = pinC

        self.pins_are_valid(self.motor_pins)
        pins_in_use.append(self.motor_pins)
        self.gpio_setup(self.motor_pins)

    def pins_are_valid(self, pins, force_selection=False):
        valid_pins = [7, 11, 12, 13, 15, 16, 18, 22, 29, 31, 32, 33, 35, 36, 37, 38, 40]
        for pin in pins:
            pin_int = int(pin)
            if (pin_int not in valid_pins) and (force_selection is not True):
                errStr =  ("GPIO pin number must be from list of valid pins: %s"
                    "\nTo use selected pins anyway, set force_selection=True "
                    "in function call." % str(valid_pins))
                raise ValueError(errStr)
            for pin_in_use in pins_in_use:
                if pin_int in pin_in_use:
                    raise ValueError('GPIO pin {} already in use.'.format(pin_int))
        self.motor_pins = pins
        return True

    def gpio_setup(self, pins):
        for pin in pins:
            if not test_mode: GPIO.setup(pin, GPIO.OUT)

    def drive_motor(self, direction=1, duration=None, wait=True):
        if not test_mode:
            if (direction == 0):
                GPIO.output(self.motor_pins[0], GPIO.LOW)
            else:
                GPIO.output(self.motor_pins[direction], GPIO.HIGH)
                GPIO.output(self.motor_pins[direction*-1], GPIO.LOW)
                GPIO.output(self.motor_pins[0], GPIO.HIGH)
        if (duration is not None) and (direction != 0):
            stop_thread = Thread(target=self.stop, args = (duration, ))
            stop_thread.start()
            if wait:
                stop_thread.join()

    def pins_string_list(self):
        return '[{}, {} and {}]'.format(*self.motor_pins)

    def spin_clockwise(self, duration=None, wait=True):
        if verbose: print('spinning motor at pins {} clockwise.'.format(self.pins_string_list()))
        self.drive_motor(direction=1, duration=duration, wait=wait)

    def spin_anticlockwise(self, duration=None, wait=True):
        if verbose: print('spinning motor at pins {} anticlockwise.'.format(self.pins_string_list()))
        self.drive_motor(direction=-1, duration=duration, wait=wait)

    def stop(self, after=0):
        if after > 0: sleep(after)
        if verbose: print('stopping motor at pins {}.'.format(self.pins_string_list()))
        if not test_mode: self.drive_motor(direction=0, duration=after, wait=True)

def cleanup():
    if not test_mode:
        try:
            GPIO.cleanup()
            if verbose: print('GPIO cleanup successful.')
        except:
            if verbose: print('GPIO cleanup failed.')

<commit_msg>Fixed #10 - Methods defined and called<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

try: # load configuration
    import config
    verbose = config.verbose
    test_mode = config.test_mode
    pin_numbering = config.pin_numbering
    config_path = config.config_path
except:
    raise ValueError('Error loading configuration.')

def print_version():
    if verbose:
        import version
        print('L293D driver version ' + version.num)

def import_gpio(): # RPi.GPIO module
    global test_mode
    try:
        import RPi.GPIO as GPIO
    except Exception as e:
        print("Can't import RPi.GPIO. Please (re)install.")
        test_mode = True
        print('Test mode has been enabled. Please view README for more info.')

def gpio_setmode(): #Sets BOARD
    global test_mode
    if not test_mode:
        try:
            GPIO.setmode(GPIO.BOARD)
            GPIO.setwarnings(False)
            if verbose: print('GPIO mode set (GPIO.BOARD)')
        except Exception as e:
            print('Can\'t set GPIO mode (GPIO.BOARD)')

from time import sleep
from threading import Thread

print_version()
import_gpio()
gpio_setmode()

pins_in_use = [] # Lists pins in use (all motors)

class motor(object):
    """
    A motor wired to the L293D chip where
    motor_pins[0] is pinA is L293D pin1 or pin9  : On or off
    motor_pins[1] is pinB is L293D pin2 or pin10 : Anticlockwise positive
    motor_pins[2] is pinC is L293D pin7 or pin15 : Clockwise positive
    """

    motor_pins = [0 for x in range(3)]

    def __init__(self, pinA=0, pinB=0, pinC=0):
        self.motor_pins[0] = pinA
        self.motor_pins[1] = pinB
        self.motor_pins[2] = pinC

        self.pins_are_valid(self.motor_pins)
        pins_in_use.append(self.motor_pins)
        self.gpio_setup(self.motor_pins)

    def pins_are_valid(self, pins, force_selection=False):
        valid_pins = [7, 11, 12, 13, 15, 16, 18, 22, 29, 31, 32, 33, 35, 36, 37, 38, 40]
        for pin in pins:
            pin_int = int(pin)
            if (pin_int not in valid_pins) and (force_selection is not True):
                errStr =  ("GPIO pin number must be from list of valid pins: %s"
                    "\nTo use selected pins anyway, set force_selection=True "
                    "in function call." % str(valid_pins))
                raise ValueError(errStr)
            for pin_in_use in pins_in_use:
                if pin_int in pin_in_use:
                    raise ValueError('GPIO pin {} already in use.'.format(pin_int))
        self.motor_pins = pins
        return True

    def gpio_setup(self, pins):
        for pin in pins:
            if not test_mode: GPIO.setup(pin, GPIO.OUT)

    def drive_motor(self, direction=1, duration=None, wait=True):
        if not test_mode:
            if (direction == 0):
                GPIO.output(self.motor_pins[0], GPIO.LOW)
            else:
                GPIO.output(self.motor_pins[direction], GPIO.HIGH)
                GPIO.output(self.motor_pins[direction*-1], GPIO.LOW)
                GPIO.output(self.motor_pins[0], GPIO.HIGH)
        if (duration is not None) and (direction != 0):
            stop_thread = Thread(target=self.stop, args = (duration, ))
            stop_thread.start()
            if wait:
                stop_thread.join()

    def pins_string_list(self):
        return '[{}, {} and {}]'.format(*self.motor_pins)

    def spin_clockwise(self, duration=None, wait=True):
        if verbose: print('spinning motor at pins {} clockwise.'.format(self.pins_string_list()))
        self.drive_motor(direction=1, duration=duration, wait=wait)

    def spin_anticlockwise(self, duration=None, wait=True):
        if verbose: print('spinning motor at pins {} anticlockwise.'.format(self.pins_string_list()))
        self.drive_motor(direction=-1, duration=duration, wait=wait)

    def stop(self, after=0):
        if after > 0: sleep(after)
        if verbose: print('stopping motor at pins {}.'.format(self.pins_string_list()))
        if not test_mode: self.drive_motor(direction=0, duration=after, wait=True)

def cleanup():
    if not test_mode:
        try:
            GPIO.cleanup()
            if verbose: print('GPIO cleanup successful.')
        except:
            if verbose: print('GPIO cleanup failed.')

<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = "Sebastián J. Seba"
__email__ = "ssebastianj[at]gmail.com"
__license__ = "GPL3"

from optparse import OptionParser
from time import sleep
import serial

def main():
    parser = OptionParser()
    parser.set_usage("Usage: %prog [-p PORT_NUMBER] [-c CALL_DELAY]" \
                     " [-u HANGUP_DELAY] [-v REDIAL_DELAY] archivo_llamadas")
    parser.add_option("-p", "--port", action="store", type="int",
                      dest="port_number",
                      help="Numero de puerto COM a utilizar [Obligatorio]")
    parser.add_option("-c", "--call-delay", action="store", type="int",
                      dest="call_delay", default=30,
                      help="Tiempo, en segundos, a esperar luego de realizar " \
                      "una llamada [Default: %default]")
    parser.add_option("-u", "--hangup-delay", action="store", type="int",
                      dest="hangup_delay", default=2,
                      help="Tiempo, en segundos, a esperar luego de cortar " \
                      "una llamada [Default: %default]")
    parser.add_option("-w", "--redial-delay", action="store", type="int",
                      dest="redial_delay", default=2,
                      help="Tiempo, en segundos, a esperar entre llamadas" \
                      "[Default: %default]")
    (options, args) = parser.parse_args()

    if len(args) == 0:
        parser.error("Pruebe '" + parser.get_prog_name() + " --help' para mas informacion.")
    elif options.port_number is None:
        parser.error('Debe ingresar un numero de puerto COM.')
    else:
        with open(args[0], 'r') as fcalls:
            calls = fcalls.readlines()

        if calls:
            try:
                print u'Conectando a módem en {0}...'.format(serial.device(
                                                             options.port_number - 1))
                modem = serial.Serial(options.port_number - 1, timeout=1)

                for call in calls:
                    print 'Marcando: {0}'.format(call)
                    modem.write('ATD' + call.strip() + '\r')
                    sleep(options.call_delay)
                    print modem.read(modem.inWaiting())

                    print 'Colgando...'
                    modem.write('ATH\r')
                    sleep(options.hangup_delay)
                    print modem.read(modem.inWaiting())
                    sleep(options.redial_delay)

                print u'Cerrando conexión...'
                modem.close()
                print 'Terminado. Presione ENTER para salir.'
                raw_input()
            except serial.SerialException:
                print 'Error al conectarse al puerto' \
                      '{0} ({1})'.format(options.port_number - 1,
                                         serial.device(options.port_number - 1))
        else:
            print 'El archivo de llamadas no contiene ninguna llamada.'

def get_registers(modem):
    registers = {}
    for j in xrange(0, 11):
        modem.write('ATS' + str(j) + '?\r')
        sleep(1.5)
        reg = modem.read(modem.inWaiting())
        reg = reg.strip('\r\n').splitlines()
        registers['S' + str(j)] = reg[2]
    return registers

if __name__ == '__main__':
    main()
<commit_msg>Arreglada longitud de cadena referida a argumento --help<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = "Sebastián J. Seba"
__email__ = "ssebastianj[at]gmail.com"
__license__ = "GPL3"

from optparse import OptionParser
from time import sleep
import serial

def main():
    parser = OptionParser()
    parser.set_usage("Usage: %prog [-p PORT_NUMBER] [-c CALL_DELAY]" \
                     " [-u HANGUP_DELAY] [-v REDIAL_DELAY] archivo_llamadas")
    parser.add_option("-p", "--port", action="store", type="int",
                      dest="port_number",
                      help="Numero de puerto COM a utilizar [Obligatorio]")
    parser.add_option("-c", "--call-delay", action="store", type="int",
                      dest="call_delay", default=30,
                      help="Tiempo, en segundos, a esperar luego de realizar " \
                      "una llamada [Default: %default]")
    parser.add_option("-u", "--hangup-delay", action="store", type="int",
                      dest="hangup_delay", default=2,
                      help="Tiempo, en segundos, a esperar luego de cortar " \
                      "una llamada [Default: %default]")
    parser.add_option("-w", "--redial-delay", action="store", type="int",
                      dest="redial_delay", default=2,
                      help="Tiempo, en segundos, a esperar entre llamadas" \
                      "[Default: %default]")
    (options, args) = parser.parse_args()

    if len(args) == 0:
        parser.error("Pruebe '" + parser.get_prog_name() + \
                     " --help' para mas informacion.")
    elif options.port_number is None:
        parser.error('Debe ingresar un numero de puerto COM.')
    else:
        with open(args[0], 'r') as fcalls:
            calls = fcalls.readlines()

        if calls:
            try:
                print u'Conectando a módem en {0}...'.format(serial.device(
                                                             options.port_number - 1))
                modem = serial.Serial(options.port_number - 1, timeout=1)

                for call in calls:
                    print 'Marcando: {0}'.format(call)
                    modem.write('ATD' + call.strip() + '\r')
                    sleep(options.call_delay)
                    print modem.read(modem.inWaiting())

                    print 'Colgando...'
                    modem.write('ATH\r')
                    sleep(options.hangup_delay)
                    print modem.read(modem.inWaiting())
                    sleep(options.redial_delay)

                print u'Cerrando conexión...'
                modem.close()
                print 'Terminado. Presione ENTER para salir.'
                raw_input()
            except serial.SerialException:
                print 'Error al conectarse al puerto' \
                      '{0} ({1})'.format(options.port_number - 1,
                                         serial.device(options.port_number - 1))
        else:
            print 'El archivo de llamadas no contiene ninguna llamada.'

def get_registers(modem):
    registers = {}
    for j in xrange(0, 11):
        modem.write('ATS' + str(j) + '?\r')
        sleep(1.5)
        reg = modem.read(modem.inWaiting())
        reg = reg.strip('\r\n').splitlines()
        registers['S' + str(j)] = reg[2]
    return registers

if __name__ == '__main__':
    main()
<|endoftext|>