コード例 #1
0
ファイル: fcubes.c プロジェクト: alpertron/calculators
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;
}
コード例 #2
0
ファイル: expression.c プロジェクト: loccs-faker/calculators
static enum eExprErr ComputeExpr(char *expr, BigInteger *ExpressionResult)
{
  int i, j, shLeft;
  int retcode;
  limb carry;
  boolean leftNumberFlag = FALSE;
  int exprIndexAux, offset;
  enum eExprErr SubExprResult;
  int len;
  limb largeLen;
  limb *ptrLimb;
  BigInteger factorial;
  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 == '!')
    {           // Calculating factorial.
      if (leftNumberFlag == FALSE)
      {
        return EXPR_SYNTAX_ERROR;
      }
      if (stackValues[stackIndex].nbrLimbs > 1)
      {
        return EXPR_INTERM_TOO_HIGH;
      }
      if (stackValues[stackIndex].limbs[0].x < 0 || stackValues[stackIndex].limbs[0].x > 5984)
      {
        return EXPR_INTERM_TOO_HIGH;
      }
      len = (int)stackValues[stackIndex].limbs[0].x;
      factorial.limbs[0].x = 1;
      factorial.nbrLimbs = 1;
      factorial.sign = SIGN_POSITIVE;
      for (i = 2; i <= len; i++)
      {   // Multiply by all integers up to the argument of factorial.
        multint(&factorial, &factorial, i);
      }
      stackValues[stackIndex] = factorial;
      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;
      }
      if (largeLen.x < 0 || largeLen.x > 46049)
      {
        return EXPR_INTERM_TOO_HIGH;
      }
      len = (int)largeLen.x;
        // Check if number is prime
      for (i = 2; i*i <= len; i++)
      {
        if (len / i*i == len)
        {   // Number is not prime, so go out.
          return EXPR_INVALID_PARAM;
        }
      }
      factorial.limbs[0].x = 1;
      factorial.nbrLimbs = 1;
      factorial.sign = SIGN_POSITIVE;
      for (i = 2; i <= len; i++)
      {      // Multiply by prime numbers only.
        for (j = 2; j*j <= i; j++)
        {
          if (i / j*j == i)
          {   // Number is not prime.
            break;
          }
        }
        if (j*j > i)
        {     // Number is prime, perform multiplication.
          multint(&factorial, &factorial, i);
        }
      }
      stackValues[stackIndex] = factorial;
      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; }
      if (BpswPrimalityTest(&stackValues[stackIndex]) == 0)
      {    // 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;
      }