Exemplo n.º 1
0
void GaussianFactorization(void)
{
  BigInteger prime, q, r, M1, M2, Tmp;
  struct sFactors *pstFactor;

  BigIntMultiply(&ReValue, &ReValue, &tofactor);
  BigIntMultiply(&ImValue, &ImValue, &Tmp);
  BigIntAdd(&tofactor, &Tmp, &tofactor);
  NbrFactorsNorm = 0;
#ifdef __EMSCRIPTEN__
  originalTenthSecond = tenths();
#endif
  if (tofactor.nbrLimbs == 1 && tofactor.limbs[0].x == 0)
  {                // Norm is zero.
    w("<ul><li>Any gaussian prime divides this number</li></ul>");
    return;
  }
  w("<ul>");
  if (tofactor.nbrLimbs > 1 || tofactor.limbs[0].x > 1)
  {           // norm greater than 1. Factor norm.
    int index, index2;
    char *ptrFactorDec = tofactorDec;
    NumberLength = tofactor.nbrLimbs;
    CompressBigInteger(nbrToFactor, &tofactor);
    strcpy(ptrFactorDec, "Re&sup2; + Im&sup2; = ");
    ptrFactorDec += strlen(ptrFactorDec);
    Bin2Dec(ReValue.limbs, ptrFactorDec, ReValue.nbrLimbs, groupLen);
    ptrFactorDec += strlen(ptrFactorDec);
    strcpy(ptrFactorDec, "&sup2; + ");
    ptrFactorDec += strlen(ptrFactorDec);
    Bin2Dec(ImValue.limbs, ptrFactorDec, ImValue.nbrLimbs, groupLen);
    ptrFactorDec += strlen(ptrFactorDec);
    strcpy(ptrFactorDec, "&sup2;");
    ptrFactorDec += strlen(ptrFactorDec);
    factor(&tofactor, nbrToFactor, factorsNorm, astFactorsNorm, NULL);
    NbrFactorsNorm = astFactorsNorm[0].multiplicity;
    pstFactor = &astFactorsNorm[1];
    for (index = 0; index < NbrFactorsNorm; index++)
    {
      int *ptrPrime = pstFactor->ptrFactor;
      NumberLength = *ptrPrime;
      UncompressBigInteger(ptrPrime, &prime);
      prime.sign = SIGN_POSITIVE;
      if (prime.nbrLimbs == 1 && prime.limbs[0].x == 2)
      {             // Prime factor is 2.
        for (index2 = 0; index2 < pstFactor->multiplicity; index2++)
        {
          M1.nbrLimbs = M2.nbrLimbs = 1;
          M1.limbs[0].x = M2.limbs[0].x = 1;
          M1.sign = SIGN_POSITIVE;
          M2.sign = SIGN_NEGATIVE;
          DivideGaussian(&M1, &M1);           // Divide by 1+i
          DivideGaussian(&M1, &M2);           // Divide by 1-i
        }
      }
      if ((prime.limbs[0].x & 2) == 0)
      {                               // Prime is congruent to 1 (mod 4)
        CopyBigInt(&q, &prime);
        NumberLength = prime.nbrLimbs;
        memcpy(&TestNbr, prime.limbs, NumberLength * sizeof(limb));
        TestNbr[NumberLength].x = 0;
        GetMontgomeryParms(NumberLength);
        subtractdivide(&q, 1, 4);     // q = (prime-1)/4
        memset(&K, 0, NumberLength * sizeof(limb));
        memset(minusOneMont, 0, NumberLength * sizeof(limb));
        SubtBigNbrModN(minusOneMont, MontgomeryMultR1, minusOneMont, TestNbr, NumberLength);
        K[0].x = 1;
        do
        {    // Loop that finds mult1 = sqrt(-1) mod prime in Montgomery notation.
          K[0].x++;
          modPow(K, q.limbs, q.nbrLimbs, mult1.limbs);
        } while (!memcmp(mult1.limbs, MontgomeryMultR1, NumberLength * sizeof(limb)) ||
                 !memcmp(mult1.limbs, minusOneMont, NumberLength * sizeof(limb)));
        K[0].x = 1;
        modmult(mult1.limbs, K, mult1.limbs);       // Convert mult1 to standard notation.
        UncompressLimbsBigInteger(mult1.limbs, &mult1);  // Convert to Big Integer.
        mult2.nbrLimbs = 1;                // mult2 <- 1
        mult2.limbs[0].x = 1;
        mult2.sign = SIGN_POSITIVE;
        for (;;)
        {
          // norm <- (mult1^2 + mult2^2) / prime
          BigIntMultiply(&mult1, &mult1, &tofactor);
          BigIntMultiply(&mult2, &mult2, &Tmp);
          BigIntAdd(&tofactor, &Tmp, &Tmp);
          BigIntDivide(&Tmp, &prime, &tofactor);
          if (tofactor.nbrLimbs == 1 && tofactor.limbs[0].x == 1)
          {        // norm equals 1.
            break;
          }
          BigIntRemainder(&mult1, &tofactor, &M1);
          BigIntRemainder(&mult2, &tofactor, &M2);
          BigIntAdd(&M1, &M1, &Tmp);
          BigIntSubt(&tofactor, &Tmp, &Tmp);
          if (Tmp.sign == SIGN_NEGATIVE)
          {
            BigIntSubt(&M1, &tofactor, &M1);
          }
          BigIntAdd(&M2, &M2, &Tmp);
          BigIntSubt(&tofactor, &Tmp, &Tmp);
          if (Tmp.sign == SIGN_NEGATIVE)
          {
            BigIntSubt(&M2, &tofactor, &M2);
          }
          // Compute q <- (mult1*M1 + mult2*M2) / norm
          BigIntMultiply(&mult1, &M1, &q);
          BigIntMultiply(&mult2, &M2, &Tmp);
          BigIntAdd(&q, &Tmp, &Tmp);
          BigIntDivide(&Tmp, &tofactor, &q);
          // Compute Mult2 <- (mult1*M2 - mult2*M1) / tofactor
          BigIntMultiply(&mult1, &M2, &r);
          BigIntMultiply(&mult2, &M1, &Tmp);
          BigIntSubt(&r, &Tmp, &Tmp);
          BigIntDivide(&Tmp, &tofactor, &mult2);
          CopyBigInt(&mult1, &q);
          mult1.sign = SIGN_POSITIVE;    // mult1 <- abs(mult1)
          mult2.sign = SIGN_POSITIVE;    // mult2 <- abs(mult2)
        }            /* end while */
        CopyBigInt(&M1, &mult1);
        CopyBigInt(&M2, &mult2);
        BigIntSubt(&M1, &M2, &Tmp);
        if (Tmp.sign == SIGN_NEGATIVE)
        {
          CopyBigInt(&Tmp, &mult1);
          CopyBigInt(&mult1, &mult2);
          CopyBigInt(&mult2, &Tmp);
        }
        for (index2 = 0; index2 < pstFactor->multiplicity; index2++)
        {
          DivideGaussian(&mult1, &mult2);
          BigIntNegate(&mult2, &Tmp);
          DivideGaussian(&mult1, &Tmp);
        }
      }              // end p = 1 (mod 4)
      else
      {              // if p = 3 (mod 4)
        q.nbrLimbs = 1;    // q <- 0
        q.limbs[0].x = 0;
        q.sign = SIGN_POSITIVE;
        for (index2 = 0; index2 < pstFactor->multiplicity; index2++)
        {
          DivideGaussian(&prime, &q);
        }            // end p = 3 (mod 4)
      }
      pstFactor++;
    }
  }
  // Process units: 1, -1, i, -i.
  if (ReValue.nbrLimbs == 1 && ReValue.limbs[0].x == 1)
  {
    if (ReValue.sign == SIGN_POSITIVE)
    {             // Value is 1.
      if (NbrFactorsNorm == 0)
      {
        w("No gaussian prime divides this number");
      }
    }
    else
    {            // Value is -1.
      w("<li>-1</li>");
    }
  }
  else if (ImValue.sign == SIGN_POSITIVE)
  {
    w("<li>i</li>");
  }
  else
  {
    w("<li>-i</li>");
  }
  w("</ul>");
}
Exemplo n.º 2
0
static int fcubes(BigInteger *pArgument)
{
  int mod18, modulus, i, mod83, mask;
  int pow, exp;
  boolean converted = FALSE;
  CopyBigInt(&value, pArgument);
  // Compute argument mod 18.
  mod18 = getRemainder(pArgument, 18);
  if (mod18 == 4 || mod18 == 5 || mod18 == 13 || mod18 == 14)
  {
    return -1;  // Applet does not work if the number is congruent to 4 or 5 (mod 9)
  }
  if (mod18 == 16)
  {             // Change sign.
    converted = TRUE;
    BigIntNegate(&value, &value);
  }
  for (i = 0; i<(int)(sizeof(sums)/sizeof(sums[0])); i += 10)
  {
    modulus = sums[i];
    if ((getRemainder(&value, modulus) + modulus)% modulus == sums[i + 1])
    {
      break;
    }
  }
  if (i<(int)(sizeof(sums) / sizeof(sums[0])))
  {
    subtractdivide(&value, sums[i + 1], modulus);      // value <- (value-sums[i+1])/modulus
    multadd(&Base1, sums[i + 2], &value, sums[i + 3]); // Base1 <- sums[i+2]*value+sums[i+3]
    multadd(&Base2, sums[i + 4], &value, sums[i + 5]); // Base2 <- sums[i+4]*value+sums[i+5]
    multadd(&Base3, sums[i + 6], &value, sums[i + 7]); // Base3 <- sums[i+6]*value+sums[i+7]
    multadd(&Base4, sums[i + 8], &value, sums[i + 9]); // Base4 <- sums[i+8]*value+sums[i+9]
  }
  else if (getRemainder(&value, 54) == 2)
  {           // If value == 2 (mod 54)...
    subtractdivide(&value, 2, 54);   // value <- (value-2)/54
    EvaluateQuadraticPoly(&Base1, &value, 29484, 2211, 43);
    EvaluateQuadraticPoly(&Base2, &value, -29484, -2157, -41);
    EvaluateQuadraticPoly(&Base3, &value, 9828, 485, 4);
    EvaluateQuadraticPoly(&Base4, &value, -9828, -971, -22);
  }
  else if (getRemainder(&value, 83 * 108) == 83*46)
  {           // If value == 83*46 (mod 83*108)...
    subtractdivide(&value, 83*46, 83*108); // value <-(value - (83*46)) / (83*108)
    EvaluateQuadraticPoly(&Base1, &value, 29484, 25143, 5371);
    EvaluateQuadraticPoly(&Base2, &value, -29484, -25089, -5348);
    EvaluateQuadraticPoly(&Base3, &value, 9828, 8129, 1682);
    EvaluateQuadraticPoly(&Base4, &value, -9828, -8615, -1889);
  }
  else
  {
      // Perform Pell solution of Demjanenko's theorem
      // Using these values of P, Q, R and S, a and b will be
      // always one and zero (mod 6) respectively.
      // P <- -112488782561 = -(52*2^31+819632865)
      // Q <- -6578430178320 = -(3063*2^31+687764496)
      // R <- -1923517596 = -(0*2^31+1923517596)
      // S <- P
      // P1 <- 1
      // Q1 <- 0
      // R1 <- 0
      // S1 <- 1
    P.limbs[1].x = S.limbs[1].x = 52;
    P.limbs[0].x = S.limbs[0].x = 819632865;
    Q.limbs[1].x = 3063;
    Q.limbs[0].x = 687764496;
    R.limbs[1].x = 0;
    R.limbs[0].x = 1923517596;
    P.nbrLimbs = Q.nbrLimbs = R.nbrLimbs = S.nbrLimbs = 3;
    P.sign = Q.sign = R.sign = S.sign = SIGN_NEGATIVE;
    P1.limbs[0].x = S1.limbs[0].x = 1;
    Q1.limbs[0].x = R1.limbs[0].x = 0;
    P1.nbrLimbs = Q1.nbrLimbs = R1.nbrLimbs = S1.nbrLimbs = 1;
    P1.sign = Q1.sign = R1.sign = S1.sign = SIGN_POSITIVE;
    mod83 = getRemainder(&value, 83);
    pow = 71;
    exp = 0;
    while (pow != mod83)
    {
      exp++;
      pow = (pow * 50) % 83;
    }
    if (exp > 82 / 2)
    {
      exp = 82 - exp;
      Q.sign = R.sign = SIGN_POSITIVE;
    }  // Now exp is in range 0-41.
    mask = 32;
    while (mask > 0)
    {
      // tmpP1 <- P1*P1 + Q1*R1
      // tmpQ1 <- (P1+S1) * Q1
      // tmpR1 <- (P1+S1) * R1
      // tmpS1 <- S1*S1 + Q1*R1
      // P1 <- tmpP1
      // Q1 <- tmpQ1
      // R1 <- tmpR1
      // S1 <- tmpS1
      (void)BigIntMultiply(&P1, &P1, &tmpP1);
      (void)BigIntMultiply(&Q1, &R1, &tmpQ1);
      (void)BigIntMultiply(&S1, &S1, &tmpS1);
      BigIntAdd(&P1, &S1, &tmpR1);
      BigIntAdd(&tmpP1, &tmpQ1, &P1);
      BigIntAdd(&tmpS1, &tmpQ1, &S1);
      (void)BigIntMultiply(&tmpR1, &Q1, &Q1);
      (void)BigIntMultiply(&tmpR1, &R1, &R1);
      if ((exp & mask) != 0)
      {
        // tmpP1 <- P*P1 + Q*R1
        // tmpQ1 <- P*Q1 + Q*S1
        // tmpR1 <- R*P1 + S*R1
        // tmpS1 <- R*Q1 + S*S1
        // P1 <- tmpP1
        // Q1 <- tmpQ1
        // R1 <- tmpR1
        // S1 <- tmpS1
        (void)BigIntMultiply(&P, &P1, &tmpP1);
        (void)BigIntMultiply(&Q, &R1, &tmpQ1);
        (void)BigIntMultiply(&R, &P1, &tmpR1);
        (void)BigIntMultiply(&S, &R1, &tmpS1);
        BigIntAdd(&tmpP1, &tmpQ1, &P1);
        BigIntAdd(&tmpR1, &tmpS1, &R1);
        (void)BigIntMultiply(&P, &Q1, &tmpP1);
        (void)BigIntMultiply(&Q, &S1, &tmpQ1);
        (void)BigIntMultiply(&R, &Q1, &tmpR1);
        (void)BigIntMultiply(&S, &S1, &tmpS1);
        BigIntAdd(&tmpP1, &tmpQ1, &Q1);
        BigIntAdd(&tmpR1, &tmpS1, &S1);
      }
      mask >>= 1;
    }
    addmult(&a, &P1, -3041, &Q1, -52);   // a <- -3041*P1 - 52*Q1
    addmult(&b, &R1, -3041, &S1, -52);   // b <- -3041*R1 - 52*S1
    addmult(&Base1, &a, 27, &b, -928);   // Base1 <- 27*a - 928*b
    addmult(&Base2, &a, -9, &b, -602);   // Base2 <- -9*a - 602*b
    addmult(&Base3, &a, 25, &b, -2937);  // Base3 <- 25*a - 2937*b
    addmult(&Base4, &a, -19, &b, 2746);  // Base4 <- -19*a - 2746*b
    // a <- (value - Base1^3 - Base2^3 - Base3^3 - Base4^3)/(18*83)
    getSumOfCubes();  // tmpP1 = Base1^3 + Base2^3 + Base3^3 + Base4^3
    BigIntSubt(&value, &tmpP1, &a);
    subtractdivide(&a, 0, 18 * 83);      // Divide a by 18*83.
    multint(&tmpP1, &a, 10);             // Base1 <- Base1 + 10*a
    BigIntAdd(&tmpP1, &Base1, &Base1);
    multint(&tmpP1, &a, -19);            // Base2 <- Base2 - 19*a
    BigIntAdd(&tmpP1, &Base2, &Base2);
    multint(&tmpP1, &a, -24);            // Base3 <- Base3 - 24*a
    BigIntAdd(&tmpP1, &Base3, &Base3);
    multint(&tmpP1, &a, 27);             // Base4 <- Base4 + 27*a
    BigIntAdd(&tmpP1, &Base4, &Base4);
  }

  if (converted != 0)
  {
    BigIntNegate(&Base1, &Base1);
    BigIntNegate(&Base2, &Base2);
    BigIntNegate(&Base3, &Base3);
    BigIntNegate(&Base4, &Base4);
  }

      // Sort cubes
  SortBigIntegers(&Base1, &Base2);
  SortBigIntegers(&Base1, &Base3);
  SortBigIntegers(&Base1, &Base4);
  SortBigIntegers(&Base2, &Base3);
  SortBigIntegers(&Base2, &Base4);
  SortBigIntegers(&Base3, &Base4);

  // Validate

  getSumOfCubes();  // tmpP1 = Base1^3 - Base2^3 - Base3^3 - Base4^3
  BigIntSubt(&tmpP1, pArgument, &tmpQ1);
  if (tmpQ1.nbrLimbs != 1 || tmpQ1.limbs[0].x != 0)
  {
    return 1;       // Result does not validate.
  }
  return 0;
}