ValueInt<Base<F>> InverseFreeSignDivide( ElementalMatrix<F>& XPre ) { DEBUG_CSE DistMatrixReadWriteProxy<F,F,MC,MR> XProx( XPre ); auto& X = XProx.Get(); typedef Base<F> Real; const Grid& g = X.Grid(); const Int n = X.Width(); if( X.Height() != 2*n ) LogicError("Matrix should be 2n x n"); // Expose A and B, and then copy A auto B = X( IR(0,n ), ALL ); auto A = X( IR(n,2*n), ALL ); DistMatrix<F> ACopy( A ); // Run the inverse-free alternative to Sign InverseFreeSign( X ); // Compute the pivoted QR decomp of inv(A + B) A [See LAWN91] // 1) B := A + B // 2) [Q,R,Pi] := QRP(A) // 3) B := Q^H B // 4) [R,Q] := RQ(B) B += A; DistMatrix<F,MD,STAR> t(g); DistMatrix<Base<F>,MD,STAR> d(g); DistMatrix<Int,VR,STAR> p(g); QR( A, t, d, p ); qr::ApplyQ( LEFT, ADJOINT, A, t, d, B ); RQ( B, t, d ); // A := Q^H A Q A = ACopy; rq::ApplyQ( LEFT, ADJOINT, B, t, d, A ); rq::ApplyQ( RIGHT, NORMAL, B, t, d, A ); // Return || E21 ||1 / || A ||1 // Return || E21 ||1 / || A ||1 ValueInt<Real> part = ComputePartition( A ); part.value /= OneNorm(ACopy); return part; }
Base<F> InverseFreeSignDivide( Matrix<F>& X ) { DEBUG_CSE typedef Base<F> Real; const Int n = X.Width(); if( X.Height() != 2*n ) LogicError("Matrix should be 2n x n"); // Expose A and B, and then copy A auto B = X( IR(0,n ), ALL ); auto A = X( IR(n,2*n), ALL ); Matrix<F> ACopy( A ); // Run the inverse-free alternative to Sign InverseFreeSign( X ); // Compute the pivoted QR decomp of inv(A + B) A [See LAWN91] // 1) B := A + B // 2) [Q,R,Pi] := QRP(A) // 3) B := Q^H B // 4) [R,Q] := RQ(B) B += A; Matrix<F> t; Matrix<Base<F>> d; Matrix<Int> p; QR( A, t, d, p ); qr::ApplyQ( LEFT, ADJOINT, A, t, d, B ); RQ( B, t, d ); // A := Q^H A Q A = ACopy; rq::ApplyQ( LEFT, ADJOINT, B, t, d, A ); rq::ApplyQ( RIGHT, NORMAL, B, t, d, A ); // Return || E21 ||1 / || A ||1 ValueInt<Real> part = ComputePartition( A ); part.value /= OneNorm(ACopy); return part; }
inline ValueInt<BASE(F)> QDWHDivide ( UpperOrLower uplo, DistMatrix<F>& A, DistMatrix<F>& G, bool returnQ=false ) { DEBUG_ONLY(CallStackEntry cse("herm_eig::QDWHDivide")) // G := sgn(G) // G := 1/2 ( G + I ) herm_polar::QDWH( uplo, G ); UpdateDiagonal( G, F(1) ); Scale( F(1)/F(2), G ); // Compute the pivoted QR decomposition of the spectral projection const Grid& g = A.Grid(); DistMatrix<F,MD,STAR> t(g); DistMatrix<Int,VR,STAR> p(g); elem::QR( G, t, p ); // A := Q^H A Q MakeHermitian( uplo, A ); const Base<F> oneA = OneNorm( A ); if( returnQ ) { ExpandPackedReflectors( LOWER, VERTICAL, CONJUGATED, 0, G, t ); DistMatrix<F> B(g); Gemm( ADJOINT, NORMAL, F(1), G, A, B ); Gemm( NORMAL, NORMAL, F(1), B, G, A ); } else { qr::ApplyQ( LEFT, ADJOINT, G, t, A ); qr::ApplyQ( RIGHT, NORMAL, G, t, A ); } // Return || E21 ||1 / || A ||1 and the chosen rank auto part = ComputePartition( A ); part.value /= oneA; return part; }
static enum eExprErr ComputeExpr(char *expr, BigInteger *ExpressionResult) { int i, shLeft; int retcode; limb carry; boolean leftNumberFlag = FALSE; int exprIndexAux, offset; enum eExprErr SubExprResult; int len; limb largeLen; limb *ptrLimb; BigInteger *pBigInt; int c; int startStackIndex = stackIndex; exprLength = (int)strlen(expr); while (exprIndex < exprLength) { char charValue; charValue = *(expr+exprIndex); if (charValue == ' ' || charValue == 9) { // Ignore spaces and horizontal tabs. exprIndex++; continue; } if (charValue == '^') { // Caret is exponentiation operation. charValue = OPER_POWER; exprIndex++; } else if (charValue == '*' && *(expr + exprIndex + 1) == '*') { // Double asterisk is exponentiation operation too. charValue = OPER_POWER; exprIndex += 2; } else if (charValue == '*') { charValue = OPER_MULTIPLY; exprIndex++; } else if (charValue == '/') { charValue = OPER_DIVIDE; exprIndex++; } else if (charValue == '%') { charValue = OPER_REMAINDER; exprIndex++; } else if (charValue == '+') { charValue = OPER_PLUS; exprIndex++; } else if (charValue == '-') { charValue = OPER_MINUS; exprIndex++; } else if (charValue == '<' && *(expr + exprIndex + 1) == '=') { charValue = OPER_NOT_GREATER; exprIndex += 2; } else if (charValue == '>' && *(expr + exprIndex + 1) == '=') { charValue = OPER_NOT_LESS; exprIndex += 2; } else if (charValue == '!' && *(expr + exprIndex + 1) == '=') { charValue = OPER_NOT_EQUAL; exprIndex += 2; } else if (charValue == '=' && *(expr + exprIndex + 1) == '=') { charValue = OPER_EQUAL; exprIndex += 2; } else if (charValue == '>') { charValue = OPER_GREATER; exprIndex++; } else if (charValue == '<') { charValue = OPER_LESS; exprIndex++; } else if ((charValue & 0xDF) == 'N' && (*(expr + exprIndex + 1) & 0xDF) == 'O' && (*(expr + exprIndex + 2) & 0xDF) == 'T') { charValue = OPER_NOT; exprIndex += 3; } else if ((charValue & 0xDF) == 'A' && (*(expr + exprIndex + 1) & 0xDF) == 'N' && (*(expr + exprIndex + 2) & 0xDF) == 'D') { charValue = OPER_AND; exprIndex += 3; } else if ((charValue & 0xDF) == 'O' && (*(expr + exprIndex + 1) & 0xDF) == 'R') { charValue = OPER_OR; exprIndex += 2; } else if ((charValue & 0xDF) == 'X' && (*(expr + exprIndex + 1) & 0xDF) == 'O' && (*(expr + exprIndex + 2) & 0xDF) == 'R') { charValue = OPER_XOR; exprIndex += 3; } else if ((charValue & 0xDF) == 'S' && (*(expr + exprIndex + 1) & 0xDF) == 'H' && (*(expr + exprIndex + 2) & 0xDF) == 'L') { charValue = OPER_SHL; exprIndex += 3; } else if ((charValue & 0xDF) == 'S' && (*(expr + exprIndex + 1) & 0xDF) == 'H' && (*(expr + exprIndex + 2) & 0xDF) == 'R') { charValue = OPER_SHR; exprIndex += 3; } else if (charValue == '!') { // Calculating factorial. if (leftNumberFlag == FALSE) { return EXPR_SYNTAX_ERROR; } if (stackValues[stackIndex].nbrLimbs > 1) { return EXPR_INTERM_TOO_HIGH; } #ifdef FACTORIZATION_APP if (stackValues[stackIndex].limbs[0].x < 0 || stackValues[stackIndex].limbs[0].x >= 47177) #else if (stackValues[stackIndex].limbs[0].x < 0 || stackValues[stackIndex].limbs[0].x >= 5984) #endif { return EXPR_INTERM_TOO_HIGH; } factorial(&stackValues[stackIndex], (int)stackValues[stackIndex].limbs[0].x); exprIndex++; continue; } else if (charValue == '#') { // Calculating primorial. if (leftNumberFlag == FALSE) { return EXPR_SYNTAX_ERROR; } if (stackValues[stackIndex].nbrLimbs > 2) { return EXPR_INTERM_TOO_HIGH; } if (stackValues[stackIndex].nbrLimbs == 2) { largeLen.x = stackValues[stackIndex].limbs[0].x + (stackValues[stackIndex].limbs[1].x << BITS_PER_GROUP); } else { largeLen.x = stackValues[stackIndex].limbs[0].x; } len = (int)largeLen.x; #ifdef FACTORIZATION_APP if (len < 0 || len > 460490) #else if (len < 0 || len > 46049) #endif { return EXPR_INTERM_TOO_HIGH; } primorial(&stackValues[stackIndex], (int)stackValues[stackIndex].limbs[0].x); exprIndex++; continue; } else if ((retcode = func(expr, ExpressionResult, "GCD", 2, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } BigIntGcd(&stackValues[stackIndex], &stackValues[stackIndex + 1], &stackValues[stackIndex]); leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "MODPOW", 3, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = BigIntGeneralModularPower(&stackValues[stackIndex], &stackValues[stackIndex + 1], &stackValues[stackIndex + 2], &stackValues[stackIndex]); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "MODINV", 2, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputeModInv(); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } #ifdef FACTORIZATION_FUNCTIONS else if ((retcode = func(expr, ExpressionResult, "TOTIENT", 1, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputeTotient(); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "NUMDIVS", 1, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputeNumDivs(); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "SUMDIVS", 1, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputeSumDivs(); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "CONCATFACT", 2, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputeConcatFact(); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } #endif else if ((retcode = func(expr, ExpressionResult, "SUMDIGITS", 2, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputeSumDigits(); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "NUMDIGITS", 2, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputeNumDigits(); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "REVDIGITS", 2, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputeRevDigits(); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "ISPRIME", 1, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } #ifdef FACTORIZATION_APP if (BpswPrimalityTest(&stackValues[stackIndex], NULL) == 0) #else if (BpswPrimalityTest(&stackValues[stackIndex]) == 0) #endif { // Argument is a probable prime. intToBigInteger(&stackValues[stackIndex], -1); } else { // Argument is not a probable prime. intToBigInteger(&stackValues[stackIndex], 0); } leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "F", 1, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputeFibLucas(0); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "L", 1, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputeFibLucas(2); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "P", 1, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputePartition(); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "N", 1, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputeNext(); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } else if ((retcode = func(expr, ExpressionResult, "B", 1, leftNumberFlag)) <= 0) { if (retcode != 0) { return retcode; } retcode = ComputeBack(); if (retcode != 0) { return retcode; } leftNumberFlag = 1; continue; } else if ((charValue & 0xDF) == 'X') { if (leftNumberFlag || valueX.nbrLimbs == 0) { return EXPR_SYNTAX_ERROR; } CopyBigInt(&stackValues[stackIndex], &valueX); valueXused = TRUE; exprIndex++; leftNumberFlag = TRUE; continue; } else if ((charValue & 0xDF) == 'C') { if (leftNumberFlag || valueX.nbrLimbs == 0) { return EXPR_SYNTAX_ERROR; } intToBigInteger(&stackValues[stackIndex], counterC); valueXused = TRUE; exprIndex++; leftNumberFlag = TRUE; continue; } else if (charValue == '(') { if (leftNumberFlag == TRUE) { return EXPR_SYNTAX_ERROR; } if (stackIndex >= PAREN_STACK_SIZE) { return EXPR_TOO_MANY_PAREN; } stackOperators[stackIndex++] = charValue; exprIndex++; continue; } else if (charValue == ')' || charValue == ',') { if (leftNumberFlag == 0) { return EXPR_SYNTAX_ERROR; } while (stackIndex > startStackIndex && stackOperators[stackIndex - 1] != '(') { if ((SubExprResult = ComputeSubExpr()) != 0) { return SubExprResult; } } if (stackIndex == startStackIndex) { break; } if (charValue == ',') { return EXPR_PAREN_MISMATCH; } stackIndex--; /* Discard ')' */ stackValues[stackIndex] = stackValues[stackIndex + 1]; leftNumberFlag = 1; exprIndex++; continue; } else if (charValue >= '0' && charValue <= '9') { exprIndexAux = exprIndex; if (charValue == '0' && exprIndexAux < exprLength - 2 && *(expr+exprIndexAux + 1) == 'x') { // hexadecimal exprIndexAux++; while (exprIndexAux < exprLength - 1) { charValue = *(expr+exprIndexAux + 1); if ((charValue >= '0' && charValue <= '9') || (charValue >= 'A' && charValue <= 'F') || (charValue >= 'a' && charValue <= 'f')) { exprIndexAux++; } else { break; } } // Generate big integer from hexadecimal number from right to left. carry.x = 0; i = 0; // limb number. shLeft = 0; offset = exprIndexAux; ptrLimb = &stackValues[stackIndex].limbs[0]; for (; exprIndexAux >= exprIndex + 2; exprIndexAux--) { c = *(expr + exprIndexAux); if (c >= '0' && c <= '9') { c -= '0'; } else if (c >= 'A' && c <= 'F') { c -= 'A' - 10; } else { c -= 'a' - 10; } carry.x += c << shLeft; shLeft += 4; // 4 bits per hex digit. if (shLeft >= BITS_PER_GROUP) { shLeft -= BITS_PER_GROUP; (ptrLimb++)->x = carry.x & MAX_VALUE_LIMB; carry.x = c >> (4-shLeft); } } if (carry.x != 0 || ptrLimb == &stackValues[stackIndex].limbs[0]) { (ptrLimb++)->x = carry.x; } exprIndex = offset+1; stackValues[stackIndex].nbrLimbs = (int)(ptrLimb - &stackValues[stackIndex].limbs[0]); stackValues[stackIndex].sign = SIGN_POSITIVE; }