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; }
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); }
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; }