예제 #1
0
bool
ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
{
    // Guard that R0 is an integer and R1 is an integer.
    Label failure;
    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);

    // Add R0 and R1. Don't need to explicitly unbox, just use R2.
    Register Rscratch = R2_;
    ARMRegister Wscratch = ARMRegister(Rscratch, 32);
#ifdef MERGE
    // DIV and MOD need an extra non-volatile ValueOperand to hold R0.
    AllocatableGeneralRegisterSet savedRegs(availableGeneralRegs(2));
    savedRegs.set() = GeneralRegisterSet::Intersect(GeneralRegisterSet::NonVolatile(), savedRegs);
#endif
    // get some more ARM-y names for the registers
    ARMRegister W0(R0_, 32);
    ARMRegister X0(R0_, 64);
    ARMRegister W1(R1_, 32);
    ARMRegister X1(R1_, 64);
    ARMRegister WTemp(ExtractTemp0, 32);
    ARMRegister XTemp(ExtractTemp0, 64);
    Label maybeNegZero, revertRegister;
    switch(op_) {
      case JSOP_ADD:
        masm.Adds(WTemp, W0, Operand(W1));

        // Just jump to failure on overflow. R0 and R1 are preserved, so we can
        // just jump to the next stub.
        masm.j(Assembler::Overflow, &failure);

        // Box the result and return. We know R0 already contains the
        // integer tag, so we just need to move the payload into place.
        masm.movePayload(ExtractTemp0, R0_);
        break;

      case JSOP_SUB:
        masm.Subs(WTemp, W0, Operand(W1));
        masm.j(Assembler::Overflow, &failure);
        masm.movePayload(ExtractTemp0, R0_);
        break;

      case JSOP_MUL:
        masm.mul32(R0.valueReg(), R1.valueReg(), Rscratch, &failure, &maybeNegZero);
        masm.movePayload(Rscratch, R0_);
        break;

      case JSOP_DIV:
      case JSOP_MOD: {

        // Check for INT_MIN / -1, it results in a double.
        Label check2;
        masm.Cmp(W0, Operand(INT_MIN));
        masm.B(&check2, Assembler::NotEqual);
        masm.Cmp(W1, Operand(-1));
        masm.j(Assembler::Equal, &failure);
        masm.bind(&check2);
        Label no_fail;
        // Check for both division by zero and 0 / X with X < 0 (results in -0).
        masm.Cmp(W1, Operand(0));
        // If x > 0, then it can't be bad.
        masm.B(&no_fail, Assembler::GreaterThan);
        // if x == 0, then ignore any comparison, and force
        // it to fail, if x < 0 (the only other case)
        // then do the comparison, and fail if y == 0
        masm.Ccmp(W0, Operand(0), vixl::ZFlag, Assembler::NotEqual);
        masm.B(&failure, Assembler::Equal);
        masm.bind(&no_fail);
        masm.Sdiv(Wscratch, W0, W1);
        // Start calculating the remainder, x - (x / y) * y.
        masm.mul(WTemp, W1, Wscratch);
        if (op_ == JSOP_DIV) {
            // Result is a double if the remainder != 0, which happens
            // when (x/y)*y != x.
            masm.branch32(Assembler::NotEqual, R0.valueReg(), ExtractTemp0, &revertRegister);
            masm.movePayload(Rscratch, R0_);
        } else {
            // Calculate the actual mod. Set the condition code, so we can see if it is non-zero.
            masm.Subs(WTemp, W0, WTemp);

            // If X % Y == 0 and X < 0, the result is -0.
            masm.Ccmp(W0, Operand(0), vixl::NoFlag, Assembler::Equal);
            masm.branch(Assembler::LessThan, &revertRegister);
            masm.movePayload(ExtractTemp0, R0_);
        }
        break;
      }
        // ORR, EOR, AND can trivially be coerced int
        // working without affecting the tag of the dest..
      case JSOP_BITOR:
        masm.Orr(X0, X0, Operand(X1));
        break;
      case JSOP_BITXOR:
        masm.Eor(X0, X0, Operand(W1, vixl::UXTW));
        break;
      case JSOP_BITAND:
        masm.And(X0, X0, Operand(X1));
        break;
        // LSH, RSH and URSH can not.
      case JSOP_LSH:
        // ARM will happily try to shift by more than 0x1f.
        masm.Lsl(Wscratch, W0, W1);
        masm.movePayload(Rscratch, R0.valueReg());
        break;
      case JSOP_RSH:
        masm.Asr(Wscratch, W0, W1);
        masm.movePayload(Rscratch, R0.valueReg());
        break;
      case JSOP_URSH:
        masm.Lsr(Wscratch, W0, W1);
        if (allowDouble_) {
            Label toUint;
            // Testing for negative is equivalent to testing bit 31
            masm.Tbnz(Wscratch, 31, &toUint);
            // Move result and box for return.
            masm.movePayload(Rscratch, R0_);
            EmitReturnFromIC(masm);

            masm.bind(&toUint);
            masm.convertUInt32ToDouble(Rscratch, ScratchDoubleReg);
            masm.boxDouble(ScratchDoubleReg, R0, ScratchDoubleReg);
        } else {
            // Testing for negative is equivalent to testing bit 31
            masm.Tbnz(Wscratch, 31, &failure);
            // Move result for return.
            masm.movePayload(Rscratch, R0_);
        }
        break;
      default:
        MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
    }

    EmitReturnFromIC(masm);

    switch (op_) {
      case JSOP_MUL:
        masm.bind(&maybeNegZero);

        // Result is -0 if exactly one of lhs or rhs is negative.
        masm.Cmn(W0, W1);
        masm.j(Assembler::Signed, &failure);

        // Result is +0, so use the zero register.
        masm.movePayload(rzr, R0_);
        EmitReturnFromIC(masm);
        break;
      case JSOP_DIV:
      case JSOP_MOD:
        masm.bind(&revertRegister);
        break;
      default:
        break;
    }

    // Failure case - jump to next stub.
    masm.bind(&failure);
    EmitStubGuardFailure(masm);

    return true;
}
예제 #2
0
MeshCurvature<Real>::MeshCurvature (int numVertices,
    const Vector3<Real>* vertices, int numTriangles, const int* indices)
{
    mNumVertices = numVertices;
    mVertices = vertices;
    mNumTriangles = numTriangles;
    mIndices = indices;

    // Compute normal vectors.
    mNormals = new1<Vector3<Real> >(mNumVertices);
    memset(mNormals, 0, mNumVertices*sizeof(Vector3<Real>));
    int i, v0, v1, v2;
    for (i = 0; i < mNumTriangles; ++i)
    {
        // Get vertex indices.
        v0 = *indices++;
        v1 = *indices++;
        v2 = *indices++;

        // Compute the normal (length provides a weighted sum).
        Vector3<Real> edge1 = mVertices[v1] - mVertices[v0];
        Vector3<Real> edge2 = mVertices[v2] - mVertices[v0];
        Vector3<Real> normal = edge1.Cross(edge2);

        mNormals[v0] += normal;
        mNormals[v1] += normal;
        mNormals[v2] += normal;
    }
    for (i = 0; i < mNumVertices; ++i)
    {
        mNormals[i].Normalize();
    }

    // Compute the matrix of normal derivatives.
    Matrix3<Real>* DNormal = new1<Matrix3<Real> >(mNumVertices);
    Matrix3<Real>* WWTrn = new1<Matrix3<Real> >(mNumVertices);
    Matrix3<Real>* DWTrn = new1<Matrix3<Real> >(mNumVertices);
    bool* DWTrnZero = new1<bool>(mNumVertices);
    memset(WWTrn, 0, mNumVertices*sizeof(Matrix3<Real>));
    memset(DWTrn, 0, mNumVertices*sizeof(Matrix3<Real>));
    memset(DWTrnZero, 0, mNumVertices*sizeof(bool));

    int row, col;
    indices = mIndices;
    for (i = 0; i < mNumTriangles; ++i)
    {
        // Get vertex indices.
        int V[3];
        V[0] = *indices++;
        V[1] = *indices++;
        V[2] = *indices++;

        for (int j = 0; j < 3; j++)
        {
            v0 = V[j];
            v1 = V[(j+1)%3];
            v2 = V[(j+2)%3];

            // Compute edge from V0 to V1, project to tangent plane of vertex,
            // and compute difference of adjacent normals.
            Vector3<Real> E = mVertices[v1] - mVertices[v0];
            Vector3<Real> W = E - (E.Dot(mNormals[v0]))*mNormals[v0];
            Vector3<Real> D = mNormals[v1] - mNormals[v0];
            for (row = 0; row < 3; ++row)
            {
                for (col = 0; col < 3; ++col)
                {
                    WWTrn[v0][row][col] += W[row]*W[col];
                    DWTrn[v0][row][col] += D[row]*W[col];
                }
            }

            // Compute edge from V0 to V2, project to tangent plane of vertex,
            // and compute difference of adjacent normals.
            E = mVertices[v2] - mVertices[v0];
            W = E - (E.Dot(mNormals[v0]))*mNormals[v0];
            D = mNormals[v2] - mNormals[v0];
            for (row = 0; row < 3; ++row)
            {
                for (col = 0; col < 3; ++col)
                {
                    WWTrn[v0][row][col] += W[row]*W[col];
                    DWTrn[v0][row][col] += D[row]*W[col];
                }
            }
        }
    }

    // Add in N*N^T to W*W^T for numerical stability.  In theory 0*0^T gets
    // added to D*W^T, but of course no update is needed in the
    // implementation.  Compute the matrix of normal derivatives.
    for (i = 0; i < mNumVertices; ++i)
    {
        for (row = 0; row < 3; ++row)
        {
            for (col = 0; col < 3; ++col)
            {
                WWTrn[i][row][col] = ((Real)0.5)*WWTrn[i][row][col] +
                    mNormals[i][row]*mNormals[i][col];
                DWTrn[i][row][col] *= (Real)0.5;
            }
        }

        // Compute the max-abs entry of D*W^T.  If this entry is (nearly)
        // zero, flag the DNormal matrix as singular.
        Real maxAbs = (Real)0;
        for (row = 0; row < 3; ++row)
        {
            for (col = 0; col < 3; ++col)
            {
                Real absEntry = Math<Real>::FAbs(DWTrn[i][row][col]);
                if (absEntry > maxAbs)
                {
                    maxAbs = absEntry;
                }
            }
        }
        if (maxAbs < (Real)1e-07)
        {
            DWTrnZero[i] = true;
        }

        DNormal[i] = DWTrn[i]*WWTrn[i].Inverse();
    }

    delete1(WWTrn);
    delete1(DWTrn);

    // If N is a unit-length normal at a vertex, let U and V be unit-length
    // tangents so that {U, V, N} is an orthonormal set.  Define the matrix
    // J = [U | V], a 3-by-2 matrix whose columns are U and V.  Define J^T
    // to be the transpose of J, a 2-by-3 matrix.  Let dN/dX denote the
    // matrix of first-order derivatives of the normal vector field.  The
    // shape matrix is
    //   S = (J^T * J)^{-1} * J^T * dN/dX * J = J^T * dN/dX * J
    // where the superscript of -1 denotes the inverse.  (The formula allows
    // for J built from non-perpendicular vectors.) The matrix S is 2-by-2.
    // The principal curvatures are the eigenvalues of S.  If k is a principal
    // curvature and W is the 2-by-1 eigenvector corresponding to it, then
    // S*W = k*W (by definition).  The corresponding 3-by-1 tangent vector at
    // the vertex is called the principal direction for k, and is J*W.
    mMinCurvatures = new1<Real>(mNumVertices);
    mMaxCurvatures = new1<Real>(mNumVertices);
    mMinDirections = new1<Vector3<Real> >(mNumVertices);
    mMaxDirections = new1<Vector3<Real> >(mNumVertices);
    for (i = 0; i < mNumVertices; ++i)
    {
        // Compute U and V given N.
        Vector3<Real> U, V;
        Vector3<Real>::GenerateComplementBasis(U, V, mNormals[i]);

        if (DWTrnZero[i])
        {
            // At a locally planar point.
            mMinCurvatures[i] = (Real)0;
            mMaxCurvatures[i] = (Real)0;
            mMinDirections[i] = U;
            mMaxDirections[i] = V;
            continue;
        }

        // Compute S = J^T * dN/dX * J.  In theory S is symmetric, but
        // because we have estimated dN/dX, we must slightly adjust our
        // calculations to make sure S is symmetric.
        Real s01 = U.Dot(DNormal[i]*V);
        Real s10 = V.Dot(DNormal[i]*U);
        Real sAvr = ((Real)0.5)*(s01 + s10);
        Matrix2<Real> S
        (
            U.Dot(DNormal[i]*U), sAvr,
            sAvr, V.Dot(DNormal[i]*V)
        );

        // Compute the eigenvalues of S (min and max curvatures).
        Real trace = S[0][0] + S[1][1];
        Real det = S[0][0]*S[1][1] - S[0][1]*S[1][0];
        Real discr = trace*trace - ((Real)4.0)*det;
        Real rootDiscr = Math<Real>::Sqrt(Math<Real>::FAbs(discr));
        mMinCurvatures[i] = ((Real)0.5)*(trace - rootDiscr);
        mMaxCurvatures[i] = ((Real)0.5)*(trace + rootDiscr);

        // Compute the eigenvectors of S.
        Vector2<Real> W0(S[0][1], mMinCurvatures[i] - S[0][0]);
        Vector2<Real> W1(mMinCurvatures[i] - S[1][1], S[1][0]);
        if (W0.SquaredLength() >= W1.SquaredLength())
        {
            W0.Normalize();
            mMinDirections[i] = W0.X()*U + W0.Y()*V;
        }
        else
        {
            W1.Normalize();
            mMinDirections[i] = W1.X()*U + W1.Y()*V;
        }

        W0 = Vector2<Real>(S[0][1], mMaxCurvatures[i] - S[0][0]);
        W1 = Vector2<Real>(mMaxCurvatures[i] - S[1][1], S[1][0]);
        if (W0.SquaredLength() >= W1.SquaredLength())
        {
            W0.Normalize();
            mMaxDirections[i] = W0.X()*U + W0.Y()*V;
        }
        else
        {
            W1.Normalize();
            mMaxDirections[i] = W1.X()*U + W1.Y()*V;
        }
    }

    delete1(DWTrnZero);
    delete1(DNormal);
}
예제 #3
0
파일: Rsimp.c 프로젝트: smdr2670/CIDGEL
int Rsimp(int m, int n, double **A, double *b, double *c,
          double *x, int *basis, int *nonbasis,
          double **R, double **Q, double *t1, double *t2){
    int i,j,k,l,q,qv;
    int max_steps=20;
    double r,a,at;
    void GQR(int,int,double**,double**);
    max_steps=4*n;

    for(k=0; k<=max_steps;k++){
        /*
   ++ Step 0) load new basis matrix and factor it
   */
        for(i=0;i<m;i++)for(j=0;j<m;j++)R0(i,j)=AB0(i,j);
        GQR(m,m,Q,R);

        /*
   ++ Step 1) solving system  B'*w=c(basis)
   ++      a) forward solve R'*y=c(basis)
   */
        for(i=0;i<m;i++){
            Y0(i)=0.0;
            for(j=0;j<i;j++)Y0(i)+=R0(j,i)*Y0(j);
            if (R0(i,i)!=0.0) Y0(i)=(CB0(i)-Y0(i))/R0(i,i);
            else {
                printf("Warning Singular Matrix Found\n");
                return LP_FAIL;
            }
        }
        /*
   ++      b) find w=Q*y
   ++         note: B'*w=(Q*R)'*Q*y= R'*(Q'*Q)*y=R'*y=c(basis)
   */
        for(i=0;i<m;i++){
            W0(i)=0.0;
            for(j=0;j<m;j++)W0(i)+=Q0(i,j)*Y0(j);
        }

        /*
   ++ Step 2)find entering variable,
   ++ (use lexicographically first variable with negative reduced cost)
   */
        q=n;
        for(i=0;i<n-m;i++){
            /* calculate reduced cost */
            r=CN0(i);
            for(j=0;j<m;j++) r-=W0(j)*AN0(j,i);
            if (r<-zero_tol && (q==n || nonbasis0(i)<nonbasis0(q))) q=i;
        }

        /*
   ++ if ratios were all nonnegative current solution is optimal
   */
        if (q==n){
            if (verbose>0) printf("optimal solution found in %d iterations\n",k);
            return LP_OPT;
        }
        /*
   ++ Step 3)Calculate translation direction for q entering
   ++        by solving system  B*d=-A(:,nonbasis(q));
   ++   a) let y=-Q'*A(:,nonbasis(q));
   */
        for(i=0;i<m;i++){
            Y0(i)=0.0;
            for(j=0;j<m;j++) Y0(i)-=Q0(j,i)*AN0(j,q);
        }

        /*
   ++  b) back solve Rd=y  (d=R\y)
   ++     note B*d= Q*R*d=Q*y=Q*-Q'*A(:nonbasis(q))=-A(:,nonbasis(q))
   */
        for(i=m-1;i>=0;i--){
            D0(i)=0.0;
            for(j=m-1;j>=i+1;j--)D0(i)+=R0(i,j)*D0(j);
            if (R0(i,i)!=0.0) D0(i)=(Y0(i)-D0(i))/R0(i,i);
            else {
                printf("Warning Singular Matrix Found\n");
                return LP_FAIL;
            }
        }
        /*
   ++ Step 4 Choose leaving variable
   ++     (first variable to become negative, by moving in direction D)
   ++     (if none become negative, then objective function unbounded)
   */
        a=0;
        l=-1;
        for(i=0;i<m;i++){
            if (D0(i)<-zero_tol){
                at=-1*XB0(i)/D0(i);
                if (l==-1 || at<a){ a=at; l=i;}
            }
        }
        if (l==-1){
            if (verbose>0){
                printf("Objective function Unbounded (%d iterations)\n",k);
            }
            return LP_UNBD;
        }
        /*
   ++ Step 5) Update solution and basis data
   */
        XN0(q)=a;
        for(j=0;j<m;j++) XB0(j)+=a*D0(j);
        XB0(l)=0.0;             /* enforce strict zeroness of nonbasis variables */
        qv=nonbasis0(q);
        nonbasis0(q)=basis0(l);
        basis0(l)=qv;
    }
    if (verbose>=0){
        printf("Simplex Algorithm did not Terminate in %d iterations\n",k);
    }
    return LP_FAIL;
}