Exemplo n.º 1
0
static void getp(dss_key *key, unsigned int size) {

	DEF_MP_INT(tempX);
	DEF_MP_INT(tempC);
	DEF_MP_INT(tempP);
	DEF_MP_INT(temp2q);
	int result;
	unsigned char *buf;

	m_mp_init_multi(&tempX, &tempC, &tempP, &temp2q, NULL);


	/* 2*q */
	if (mp_mul_d(key->q, 2, &temp2q) != MP_OKAY) {
		fprintf(stderr, "dss key generation failed\n");
		exit(1);
	}
	
	buf = (unsigned char*)m_malloc(size);

	result = 0;
	do {
		
		genrandom(buf, size);
		buf[0] |= 0x80; /* set the top bit high */

		/* X is a random mp_int */
		bytes_to_mp(&tempX, buf, size);

		/* C = X mod 2q */
		if (mp_mod(&tempX, &temp2q, &tempC) != MP_OKAY) {
			fprintf(stderr, "dss key generation failed\n");
			exit(1);
		}

		/* P = X - (C - 1) = X - C + 1*/
		if (mp_sub(&tempX, &tempC, &tempP) != MP_OKAY) {
			fprintf(stderr, "dss key generation failed\n");
			exit(1);
		}
		
		if (mp_add_d(&tempP, 1, key->p) != MP_OKAY) {
			fprintf(stderr, "dss key generation failed\n");
			exit(1);
		}

		/* now check for prime, 5 rounds is enough according to HAC */
		/* result == 1  =>  p is prime */
		if (mp_prime_is_prime(key->p, 5, &result) != MP_OKAY) {
			fprintf(stderr, "dss key generation failed\n");
			exit(1);
		}
	} while (!result);

	mp_clear_multi(&tempX, &tempC, &tempP, &temp2q, NULL);
	m_burn(buf, size);
	m_free(buf);
}
Exemplo n.º 2
0
/* read a bigint from a file stream in ASCII */
int mp_fread(mp_int *a, int radix, FILE *stream)
{
   int err, ch, neg, y;
   unsigned pos;

   /* clear a */
   mp_zero(a);

   /* if first digit is - then set negative */
   ch = fgetc(stream);
   if (ch == (int)'-') {
      neg = MP_NEG;
      ch = fgetc(stream);
   } else {
      neg = MP_ZPOS;
   }

   for (;;) {
      pos = (unsigned)(ch - (int)'(');
      if (mp_s_rmap_reverse_sz < pos) {
         break;
      }

      y = (int)mp_s_rmap_reverse[pos];

      if ((y == 0xff) || (y >= radix)) {
         break;
      }

      /* shift up and add */
      if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) {
         return err;
      }
      if ((err = mp_add_d(a, (mp_digit)y, a)) != MP_OKAY) {
         return err;
      }

      ch = fgetc(stream);
   }
   if (mp_cmp_d(a, 0uL) != MP_EQ) {
      a->sign = neg;
   }

   return MP_OKAY;
}
Exemplo n.º 3
0
/* read a bigint from a file stream in ASCII */
int mp_fread(mp_int *a, int radix, FILE *stream)
{
   int err, ch, neg, y;

   /* clear a */
   mp_zero(a);

   /* if first digit is - then set negative */
   ch = fgetc(stream);
   if (ch == '-') {
      neg = MP_NEG;
      ch = fgetc(stream);
   } else {
      neg = MP_ZPOS;
   }

   for (;;) {
      /* find y in the radix map */
      for (y = 0; y < radix; y++) {
          if (mp_s_rmap[y] == ch) {
             break;
          }
      }
      if (y == radix) {
         break;
      }

      /* shift up and add */
      if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
         return err;
      }
      if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
         return err;
      }

      ch = fgetc(stream);
   }
   if (mp_cmp_d(a, 0) != MP_EQ) {
      a->sign = neg;
   }

   return MP_OKAY;
}
Exemplo n.º 4
0
void ecc_gen(void)
{
   FILE         *out;
   unsigned char str[512];
   void          *k, *order, *modulus;
   ecc_point    *G, *R;
   int           x;

   out = fopen("ecc_tv.txt", "w");
   fprintf(out, "ecc vectors.  These are for kG for k=1,3,9,27,...,3**n until k > order of the curve outputs are <k,x,y> triplets\n\n");
   G = ltc_ecc_new_point();
   R = ltc_ecc_new_point();
   mp_init(&k);
   mp_init(&order);
   mp_init(&modulus);

   for (x = 0; ltc_ecc_sets[x].size != 0; x++) {
        fprintf(out, "ECC-%d\n", ltc_ecc_sets[x].size*8);
        mp_set(k, 1);

        mp_read_radix(order,   (char *)ltc_ecc_sets[x].order, 16);
        mp_read_radix(modulus, (char *)ltc_ecc_sets[x].prime, 16);
        mp_read_radix(G->x,    (char *)ltc_ecc_sets[x].Gx,    16);
        mp_read_radix(G->y,    (char *)ltc_ecc_sets[x].Gy,    16);
        mp_set(G->z, 1);

        while (mp_cmp(k, order) == LTC_MP_LT) {
            ltc_mp.ecc_ptmul(k, G, R, modulus, 1);
            mp_tohex(k,    (char*)str); fprintf(out, "%s, ", (char*)str);
            mp_tohex(R->x, (char*)str); fprintf(out, "%s, ", (char*)str);
            mp_tohex(R->y, (char*)str); fprintf(out, "%s\n", (char*)str);
            mp_mul_d(k, 3, k);
        }
   }
   mp_clear_multi(k, order, modulus, NULL);
   ltc_ecc_del_point(G);
   ltc_ecc_del_point(R);
   fclose(out);
}
Exemplo n.º 5
0
/* reduces a modulo n where n is of the form 2**p - d */
int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
{
   mp_int q;
   int    p, res;

   if ((res = mp_init(&q)) != MP_OKAY) {
      return res;
   }

   p = mp_count_bits(n);
top:
   /* q = a/2**p, a = a mod 2**p */
   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
      goto ERR;
   }

   if (d != 1) {
      /* q = q * d */
      if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) {
         goto ERR;
      }
   }

   /* a = a + q */
   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
      goto ERR;
   }

   if (mp_cmp_mag(a, n) != MP_LT) {
      if ((res = s_mp_sub(a, n, a)) != MP_OKAY) {
         goto ERR;
      }
      goto top;
   }

ERR:
   mp_clear(&q);
   return res;
}
Exemplo n.º 6
0
/* read a string [ASCII] in a given radix */
int mp_read_radix (mp_int * a, const char *str, int radix)
{
  int     y, res, neg;
  char    ch;

  /* zero the digit bignum */
  mp_zero(a);

  /* make sure the radix is ok */
  if ((radix < 2) || (radix > 64)) {
    return MP_VAL;
  }

  /* if the leading digit is a 
   * minus set the sign to negative. 
   */
  if (*str == '-') {
    ++str;
    neg = MP_NEG;
  } else {
    neg = MP_ZPOS;
  }

  /* set the integer to the default of zero */
  mp_zero (a);
  
  /* process each digit of the string */
  while (*str != '\0') {
    /* if the radix <= 36 the conversion is case insensitive
     * this allows numbers like 1AB and 1ab to represent the same  value
     * [e.g. in hex]
     */
    ch = (radix <= 36) ? (char)toupper((int)*str) : *str;
    for (y = 0; y < 64; y++) {
      if (ch == mp_s_rmap[y]) {
         break;
      }
    }

    /* if the char was found in the map 
     * and is less than the given radix add it
     * to the number, otherwise exit the loop. 
     */
    if (y < radix) {
      if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
         return res;
      }
      if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
         return res;
      }
    } else {
      break;
    }
    ++str;
  }
  
  /* set the sign only if a != 0 */
  if (mp_iszero(a) != MP_YES) {
     a->sign = neg;
  }
  return MP_OKAY;
}
Exemplo n.º 7
0
static int
TestbignumobjCmd(
    ClientData clientData,	/* unused */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Argument count */
    Tcl_Obj *const objv[])	/* Argument vector */
{
    const char *const subcmds[] = {
	"set",	    "get",	"mult10",	"div10", NULL
    };
    enum options {
	BIGNUM_SET, BIGNUM_GET,	BIGNUM_MULT10,	BIGNUM_DIV10
    };
    int index, varIndex;
    const char *string;
    mp_int bignumValue, newValue;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }
    string = Tcl_GetString(objv[2]);
    if (GetVariableIndex(interp, string, &varIndex) != TCL_OK) {
	return TCL_ERROR;
    }

    switch (index) {
    case BIGNUM_SET:
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "var value");
	    return TCL_ERROR;
	}
	string = Tcl_GetString(objv[3]);
	if (mp_init(&bignumValue) != MP_OKAY) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("error in mp_init", -1));
	    return TCL_ERROR;
	}
	if (mp_read_radix(&bignumValue, string, 10) != MP_OKAY) {
	    mp_clear(&bignumValue);
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("error in mp_read_radix", -1));
	    return TCL_ERROR;
	}

	/*
	 * If the object currently bound to the variable with index varIndex
	 * has ref count 1 (i.e. the object is unshared) we can modify that
	 * object directly.  Otherwise, if RC>1 (i.e. the object is shared),
	 * we must create a new object to modify/set and decrement the old
	 * formerly-shared object's ref count. This is "copy on write".
	 */

	if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetBignumObj(varPtr[varIndex], &bignumValue);
	} else {
	    SetVarToObj(varIndex, Tcl_NewBignumObj(&bignumValue));
	}
	break;

    case BIGNUM_GET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varIndex)) {
	    return TCL_ERROR;
	}
	break;

    case BIGNUM_MULT10:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBignumFromObj(interp, varPtr[varIndex],
		&bignumValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (mp_init(&newValue) != MP_OKAY
		|| (mp_mul_d(&bignumValue, 10, &newValue) != MP_OKAY)) {
	    mp_clear(&bignumValue);
	    mp_clear(&newValue);
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("error in mp_mul_d", -1));
	    return TCL_ERROR;
	}
	mp_clear(&bignumValue);
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetBignumObj(varPtr[varIndex], &newValue);
	} else {
	    SetVarToObj(varIndex, Tcl_NewBignumObj(&newValue));
	}
	break;

    case BIGNUM_DIV10:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBignumFromObj(interp, varPtr[varIndex],
		&bignumValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (mp_init(&newValue) != MP_OKAY
		|| (mp_div_d(&bignumValue, 10, &newValue, NULL) != MP_OKAY)) {
	    mp_clear(&bignumValue);
	    mp_clear(&newValue);
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("error in mp_div_d", -1));
	    return TCL_ERROR;
	}
	mp_clear(&bignumValue);
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetBignumObj(varPtr[varIndex], &newValue);
	} else {
	    SetVarToObj(varIndex, Tcl_NewBignumObj(&newValue));
	}
    }

    Tcl_SetObjResult(interp, varPtr[varIndex]);
    return TCL_OK;
}
Exemplo n.º 8
0
/* multiplication using the Toom-Cook 3-way algorithm 
 *
 * Much more complicated than Karatsuba but has a lower 
 * asymptotic running time of O(N**1.464).  This algorithm is 
 * only particularly useful on VERY large inputs 
 * (we're talking 1000s of digits here...).
*/
int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
{
    mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
    int res, B;
        
    /* init temps */
    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, 
                             &a0, &a1, &a2, &b0, &b1, 
                             &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
       return res;
    }
    
    /* B */
    B = MIN(a->used, b->used) / 3;
    
    /* a = a2 * B**2 + a1 * B + a0 */
    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a1, B);
    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);

    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a2, B*2);
    
    /* b = b2 * B**2 + b1 * B + b0 */
    if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_copy(b, &b1)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&b1, B);
    mp_mod_2d(&b1, DIGIT_BIT * B, &b1);

    if ((res = mp_copy(b, &b2)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&b2, B*2);
    
    /* w0 = a0*b0 */
    if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w4 = a2 * b2 */
    if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
       goto ERR;
    }
    

    /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
       goto ERR;
    }
    
    /* now solve the matrix 
    
       0  0  0  0  1
       1  2  4  8  16
       1  1  1  1  1
       16 8  4  2  1
       1  0  0  0  0
       
       using 12 subtractions, 4 shifts, 
              2 small divisions and 1 small multiplication 
     */
     
     /* r1 - r4 */
     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r0 */
     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/2 */
     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/2 */
     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r2 - r0 - r4 */
     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - 8r0 */
     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - 8r4 */
     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* 3r2 - r1 - r3 */
     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/3 */
     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/3 */
     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
        goto ERR;
     }
     
     /* at this point shift W[n] by B*n */
     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
        goto ERR;
     }     
     
     if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
        goto ERR;
     }     
     
ERR:
     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, 
                    &a0, &a1, &a2, &b0, &b1, 
                    &b2, &tmp1, &tmp2, NULL);
     return res;
}     
Exemplo n.º 9
0
int main(void)
{
    int n, tmp;
    mp_int a, b, c, d, e;
    clock_t t1;
    char buf[4096];

    mp_init(&a);
    mp_init(&b);
    mp_init(&c);
    mp_init(&d);
    mp_init(&e);


    /* initial (2^n - 1)^2 testing, makes sure the comba multiplier works [it has the new carry code] */
    /*
       mp_set(&a, 1);
       for (n = 1; n < 8192; n++) {
           mp_mul(&a, &a, &c);
           printf("mul\n");
           mp_to64(&a, buf);
           printf("%s\n%s\n", buf, buf);
           mp_to64(&c, buf);
           printf("%s\n", buf);

           mp_add_d(&a, 1, &a);
           mp_mul_2(&a, &a);
           mp_sub_d(&a, 1, &a);
       }
    */

    rng = fopen("/dev/urandom", "rb");
    if (rng == NULL) {
        rng = fopen("/dev/random", "rb");
        if (rng == NULL) {
            fprintf(stderr, "\nWarning:  stdin used as random source\n\n");
            rng = stdin;
        }
    }

    t1 = clock();
    for (;;) {
#if 0
        if (clock() - t1 > CLOCKS_PER_SEC) {
            sleep(2);
            t1 = clock();
        }
#endif
        n = fgetc(rng) % 16;
        if (n == 0) {
            /* add tests */
            rand_num(&a);
            rand_num(&b);
            mp_add(&a, &b, &c);
            printf("add\n");
            mp_to64(&a, buf);
            printf("%s\n", buf);
            mp_to64(&b, buf);
            printf("%s\n", buf);
            mp_to64(&c, buf);
            printf("%s\n", buf);
        } else if (n == 1) {
            /* sub tests */
            rand_num(&a);
            rand_num(&b);
            mp_sub(&a, &b, &c);
            printf("sub\n");
            mp_to64(&a, buf);
            printf("%s\n", buf);
            mp_to64(&b, buf);
            printf("%s\n", buf);
            mp_to64(&c, buf);
            printf("%s\n", buf);
        } else if (n == 2) {
            /* mul tests */
            rand_num(&a);
            rand_num(&b);
            mp_mul(&a, &b, &c);
            printf("mul\n");
            mp_to64(&a, buf);
            printf("%s\n", buf);
            mp_to64(&b, buf);
            printf("%s\n", buf);
            mp_to64(&c, buf);
            printf("%s\n", buf);
        } else if (n == 3) {
            /* div tests */
            rand_num(&a);
            rand_num(&b);
            mp_div(&a, &b, &c, &d);
            printf("div\n");
            mp_to64(&a, buf);
            printf("%s\n", buf);
            mp_to64(&b, buf);
            printf("%s\n", buf);
            mp_to64(&c, buf);
            printf("%s\n", buf);
            mp_to64(&d, buf);
            printf("%s\n", buf);
        } else if (n == 4) {
            /* sqr tests */
            rand_num(&a);
            mp_sqr(&a, &b);
            printf("sqr\n");
            mp_to64(&a, buf);
            printf("%s\n", buf);
            mp_to64(&b, buf);
            printf("%s\n", buf);
        } else if (n == 5) {
            /* mul_2d test */
            rand_num(&a);
            mp_copy(&a, &b);
            n = fgetc(rng) & 63;
            mp_mul_2d(&b, n, &b);
            mp_to64(&a, buf);
            printf("mul2d\n");
            printf("%s\n", buf);
            printf("%d\n", n);
            mp_to64(&b, buf);
            printf("%s\n", buf);
        } else if (n == 6) {
            /* div_2d test */
            rand_num(&a);
            mp_copy(&a, &b);
            n = fgetc(rng) & 63;
            mp_div_2d(&b, n, &b, NULL);
            mp_to64(&a, buf);
            printf("div2d\n");
            printf("%s\n", buf);
            printf("%d\n", n);
            mp_to64(&b, buf);
            printf("%s\n", buf);
        } else if (n == 7) {
            /* gcd test */
            rand_num(&a);
            rand_num(&b);
            a.sign = MP_ZPOS;
            b.sign = MP_ZPOS;
            mp_gcd(&a, &b, &c);
            printf("gcd\n");
            mp_to64(&a, buf);
            printf("%s\n", buf);
            mp_to64(&b, buf);
            printf("%s\n", buf);
            mp_to64(&c, buf);
            printf("%s\n", buf);
        } else if (n == 8) {
            /* lcm test */
            rand_num(&a);
            rand_num(&b);
            a.sign = MP_ZPOS;
            b.sign = MP_ZPOS;
            mp_lcm(&a, &b, &c);
            printf("lcm\n");
            mp_to64(&a, buf);
            printf("%s\n", buf);
            mp_to64(&b, buf);
            printf("%s\n", buf);
            mp_to64(&c, buf);
            printf("%s\n", buf);
        } else if (n == 9) {
            /* exptmod test */
            rand_num2(&a);
            rand_num2(&b);
            rand_num2(&c);
            a.sign = b.sign = c.sign = 0;
            c.dp[0] |= 1;
//      if (c.used <= 4) continue;
//      if (mp_cmp(&a, &c) != MP_LT) continue;
//      if (mp_cmp(&b, &c) != MP_LT) continue;
            mp_exptmod(&a, &b, &c, &d);
            printf("expt\n");
            mp_to64(&a, buf);
            printf("%s\n", buf);
            mp_to64(&b, buf);
            printf("%s\n", buf);
            mp_to64(&c, buf);
            printf("%s\n", buf);
            mp_to64(&d, buf);
            printf("%s\n", buf);
        } else if (n == 10) {
            /* invmod test */
            rand_num2(&a);
            rand_num2(&b);
            b.dp[0] |= 1;
            b.sign = MP_ZPOS;
            a.sign = MP_ZPOS;
            mp_gcd(&a, &b, &c);
            if (mp_cmp_d(&c, 1) != 0) continue;
            if (mp_cmp_d(&b, 1) == 0) continue;
            mp_invmod(&a, &b, &c);
            printf("invmod\n");
            mp_to64(&a, buf);
            printf("%s\n", buf);
            mp_to64(&b, buf);
            printf("%s\n", buf);
            mp_to64(&c, buf);
            printf("%s\n", buf);
        } else if (n == 11) {
            rand_num(&a);
            mp_mul_2(&a, &a);
            mp_div_2(&a, &b);
            printf("div2\n");
            mp_to64(&a, buf);
            printf("%s\n", buf);
            mp_to64(&b, buf);
            printf("%s\n", buf);
        } else if (n == 12) {
            rand_num(&a);
            mp_mul_2(&a, &b);
            printf("mul2\n");
            mp_to64(&a, buf);
            printf("%s\n", buf);
            mp_to64(&b, buf);
            printf("%s\n", buf);
        } else if (n == 13) {
            rand_num(&a);
            tmp = abs(rand()) & THE_MASK;
            mp_add_d(&a, tmp, &b);
            printf("add_d\n");
            mp_to64(&a, buf);
            printf("%s\n%d\n", buf, tmp);
            mp_to64(&b, buf);
            printf("%s\n", buf);
        } else if (n == 14) {
            rand_num(&a);
            tmp = abs(rand()) & THE_MASK;
            mp_sub_d(&a, tmp, &b);
            printf("sub_d\n");
            mp_to64(&a, buf);
            printf("%s\n%d\n", buf, tmp);
            mp_to64(&b, buf);
            printf("%s\n", buf);
        } else if (n == 15) {
            rand_num(&a);
            tmp = abs(rand()) & THE_MASK;
            mp_mul_d(&a, tmp, &b);
            printf("mul_d\n");
            mp_to64(&a, buf);
            printf("%s\n%d\n", buf, tmp);
            mp_to64(&b, buf);
            printf("%s\n", buf);
        }
    }
    fclose(rng);
    return 0;
}
Exemplo n.º 10
0
/* read a string [ASCII] in a given radix */
int mp_read_radix(mp_int *a, const char *str, int radix)
{
   int     y, res, neg;
   unsigned pos;
   char    ch;

   /* zero the digit bignum */
   mp_zero(a);

   /* make sure the radix is ok */
   if ((radix < 2) || (radix > 64)) {
      return MP_VAL;
   }

   /* if the leading digit is a
    * minus set the sign to negative.
    */
   if (*str == '-') {
      ++str;
      neg = MP_NEG;
   } else {
      neg = MP_ZPOS;
   }

   /* set the integer to the default of zero */
   mp_zero(a);

   /* process each digit of the string */
   while (*str != '\0') {
      /* if the radix <= 36 the conversion is case insensitive
       * this allows numbers like 1AB and 1ab to represent the same  value
       * [e.g. in hex]
       */
      ch = (radix <= 36) ? (char)toupper((int)*str) : *str;
      pos = (unsigned)(ch - '(');
      if (mp_s_rmap_reverse_sz < pos) {
         break;
      }
      y = (int)mp_s_rmap_reverse[pos];

      /* if the char was found in the map
       * and is less than the given radix add it
       * to the number, otherwise exit the loop.
       */
      if ((y == 0xff) || (y >= radix)) {
         break;
      }
      if ((res = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) {
         return res;
      }
      if ((res = mp_add_d(a, (mp_digit)y, a)) != MP_OKAY) {
         return res;
      }
      ++str;
   }

   /* if an illegal character was found, fail. */
   if (!((*str == '\0') || (*str == '\r') || (*str == '\n'))) {
      mp_zero(a);
      return MP_VAL;
   }

   /* set the sign only if a != 0 */
   if (mp_iszero(a) != MP_YES) {
      a->sign = neg;
   }
   return MP_OKAY;
}
Exemplo n.º 11
0
int mp_toom_cook_5_mul(mp_int *a, mp_int *b, mp_int *c)
{
   mp_int w1, w2, w3, w4, w5, w6, w7, w8, w9;
   mp_int tmp1, tmp2;
   mp_int a0, a1, a2, a3, a4;
   mp_int b0, b1, b2, b3, b4;
   int e = MP_OKAY;
   int B, count, sign;

   B = (MAX(a->used, b->used)) / 5;


   sign = (a->sign != b->sign) ? MP_NEG : MP_ZPOS;
   if (MIN(a->used, b->used) < TOOM_COOK_5_MUL_CO) {
      if ((e = mp_mul(a, b, c)) != MP_OKAY) {
         return e;
      }
      c->sign = sign;
      return MP_OKAY;
   }



   if ((e =
           mp_init_multi(&w1, &w2, &w3, &w4, &w5, &w6, &w7, &w8, &w9, &tmp1, &tmp2,
                         //&a0, &a1, &a2, &a3, &a4, &b0, &b1, &b2, &b3, &b4,
                         NULL)) != MP_OKAY) {
      goto ERR0;
      //goto ERR;
   }

   if ((e = mp_init_size(&a0, B)) != MP_OKAY) {
      goto ERRa0;
   }
   if ((e = mp_init_size(&a1, B)) != MP_OKAY) {
      goto ERRa1;
   }
   if ((e = mp_init_size(&a2, B)) != MP_OKAY) {
      goto ERRa2;
   }
   if ((e = mp_init_size(&a3, B)) != MP_OKAY) {
      goto ERRa3;
   }
   if ((e = mp_init_size(&a4, B)) != MP_OKAY) {
      goto ERRa4;
   }

   if ((e = mp_init_size(&b0, B)) != MP_OKAY) {
      goto ERRb0;
   }
   if ((e = mp_init_size(&b1, B)) != MP_OKAY) {
      goto ERRb1;
   }
   if ((e = mp_init_size(&b2, B)) != MP_OKAY) {
      goto ERRb2;
   }
   if ((e = mp_init_size(&b3, B)) != MP_OKAY) {
      goto ERRb3;
   }
   if ((e = mp_init_size(&b4, B)) != MP_OKAY) {
      goto ERRb4;
   }
   // A = a4*x^4 + a3*x^3 + a2*x^2 + a1*x + a0
   for (count = 0; count < a->used; count++) {
      switch (count / B) {
      case 0:
         a0.dp[count] = a->dp[count];
         a0.used++;
         break;
      case 1:
         a1.dp[count - B] = a->dp[count];
         a1.used++;
         break;
      case 2:
         a2.dp[count - 2 * B] = a->dp[count];
         a2.used++;
         break;
      case 3:
         a3.dp[count - 3 * B] = a->dp[count];
         a3.used++;
         break;
      case 4:
         a4.dp[count - 4 * B] = a->dp[count];
         a4.used++;
         break;
      default:
         a4.dp[count - 4 * B] = a->dp[count];
         a4.used++;
         break;
      }
   }
   mp_clamp(&a0);
   mp_clamp(&a1);
   mp_clamp(&a2);
   mp_clamp(&a3);
   mp_clamp(&a4);
   // B = b4*x^4 + b3*x^3 + b2*x^2 + b1*x + b0
   for (count = 0; count < b->used; count++) {
      switch (count / B) {
      case 0:
         b0.dp[count] = b->dp[count];
         b0.used++;
         break;
      case 1:
         b1.dp[count - B] = b->dp[count];
         b1.used++;
         break;
      case 2:
         b2.dp[count - 2 * B] = b->dp[count];
         b2.used++;
         break;
      case 3:
         b3.dp[count - 3 * B] = b->dp[count];
         b3.used++;
         break;
      case 4:
         b4.dp[count - 4 * B] = b->dp[count];
         b4.used++;
         break;
      default:
         b4.dp[count - 4 * B] = b->dp[count];
         b4.used++;
         break;
      }
   }
   mp_clamp(&b0);
   mp_clamp(&b1);
   mp_clamp(&b2);
   mp_clamp(&b3);
   mp_clamp(&b4);


   /*
     if ((e = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
       goto ERR;
     }

     if ((e = mp_copy(a, &a1)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&a1, B);
     mp_mod_2d(&a1, DIGIT_BIT * B, &a1);

     if ((e = mp_copy(a, &a2)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&a2, B * 2);
     mp_mod_2d(&a2, DIGIT_BIT * B, &a2);

     if ((e = mp_copy(a, &a3)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&a3, B * 3);

     mp_mod_2d(&a3, DIGIT_BIT * B, &a3);

     if ((e = mp_copy(a, &a4)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&a4, B * 4);



     if ((e = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
       goto ERR;
     }

     if ((e = mp_copy(a, &b1)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&b1, B);
     mp_mod_2d(&b1, DIGIT_BIT * B, &b1);

     if ((e = mp_copy(b, &b2)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&b2, B * 2);
     mp_mod_2d(&b2, DIGIT_BIT * B, &b2);

     if ((e = mp_copy(b, &b3)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&b3, B * 3);

     mp_mod_2d(&b3, DIGIT_BIT * B, &b3);

     if ((e = mp_copy(b, &b4)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&b4, B * 4);
   */

// S1 = a4*b4
   if ((e = mp_mul(&a4, &b4, &w1)) != MP_OKAY) {
      goto ERR;
   }
// S9 = a0*b0
   if ((e = mp_mul(&a0, &b0, &w9)) != MP_OKAY) {
      goto ERR;
   }

// S2 = (a0- 2*a1 +4*a2 -8*a3 +16*a4)

   if ((e = mp_mul_2d(&a1, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }            // 2*a1     = tmp1
   if ((e = mp_sub(&a0, &tmp1, &w2)) != MP_OKAY) {
      goto ERR;
   }            // a0- 2*a1 = a0 - tmp1 = w2
   if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }            // 4*a2     = tmp1
   if ((e = mp_add(&w2, &tmp1, &w2)) != MP_OKAY) {
      goto ERR;
   }            // a0- 2*a1 +4*a2 = w2 + tmp1 = w2
   if ((e = mp_mul_2d(&a3, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }            // 8*a3     = tmp1
   if ((e = mp_sub(&w2, &tmp1, &w2)) != MP_OKAY) {
      goto ERR;
   }            // a0- 2*a1 +4*a2 -8*a3 = w2 - tmp1 = w2
   if ((e = mp_mul_2d(&a4, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }            // 16*a4     = tmp1
   if ((e = mp_add(&w2, &tmp1, &w2)) != MP_OKAY) {
      goto ERR;
   }            // a0- 2*a1 +4*a2 -8*a3 +16*a4 = w2 + tmp1 = w2

//    * (b0- 2*b1 +4*b2 -8*b3 +16*b4)
   if ((e = mp_mul_2d(&b1, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&b0, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b3, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b4, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w2, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S5 = (a0+ 2*a1+ 4*a2+ 8*a3+ 16*a4)
   if ((e = mp_mul_2d(&a1, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&a0, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a3, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a4, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
// *(b0+ 2*b1+ 4*b2+ 8*b3+ 16*b4)
   if ((e = mp_mul_2d(&b1, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&b0, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b3, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b4, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w5, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S3 = (a4+ 2*a3+ 4*a2+ 8*a1+ 16*a0)
   if ((e = mp_mul_2d(&a3, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&a4, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a1, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a0, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
// *    (b4+ 2*b3+ 4*b2+ 8*b1+ 16*b0)
   if ((e = mp_mul_2d(&b3, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&b4, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b1, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b0, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w3, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S8 = (a4- 2*a3+ 4*a2- 8*a1+ 16*a0)
   if ((e = mp_mul_2d(&a3, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&a4, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w8, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a1, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w8, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a0, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w8, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
//*     (b4- 2*b3+ 4*b2- 8*b1+ 16*b0)
   if ((e = mp_mul_2d(&b3, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&b4, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b1, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b0, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w8, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S4 = (a0+ 4*a1+ 16*a2+ 64*a3+ 256*a4)
   if ((e = mp_mul_2d(&a1, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&a0, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a2, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a3, 6, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a4, 8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
//*     (b0+ 4*b1+ 16*b2+ 64*b3+ 256*b4)
   if ((e = mp_mul_2d(&b1, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&b0, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b3, 6, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b4, 8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w4, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S6 = (a0- a1+ a2- a3 +a4)
   if ((e = mp_sub(&a0, &a1, &w6)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w6, &a2, &w6)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w6, &a3, &w6)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w6, &a4, &w6)) != MP_OKAY) {
      goto ERR;
   }
// *    (b0- b1+ b2- b3+ b4)
   if ((e = mp_sub(&b0, &b1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&tmp1, &b3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp1, &w6, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S7 = (a0+ a1+ a2+ a3+ a4)
   if ((e = mp_add(&a0, &a1, &w7)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w7, &a2, &w7)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w7, &a3, &w7)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w7, &a4, &w7)) != MP_OKAY) {
      goto ERR;
   }
// *    (b0+ b1+ b2+ b3+ b4)
   if ((e = mp_add(&b0, &b1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp1, &w7, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S6 -= S7
   if ((e = mp_sub(&w6, &w7, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S2 -= S5
   if ((e = mp_sub(&w2, &w5, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= S9
   if ((e = mp_sub(&w4, &w9, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= (2^16*S1)
   if ((e = mp_mul_2d(&w1, 16, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S8 -= S3
   if ((e = mp_sub(&w8, &w3, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S6 /= 2
   if ((e = mp_div_2d(&w6, 1, &w6, NULL)) != MP_OKAY) {
      goto ERR;
   }
// S5 *= 2
   if ((e = mp_mul_2d(&w5, 1, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S5 += S2
   if ((e = mp_add(&w5, &w2, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S2 = -S2
   if ((e = mp_neg(&w2, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S8 = -S8
   if ((e = mp_neg(&w8, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S7 += S6
   if ((e = mp_add(&w7, &w6, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S6 = -S6
   if ((e = mp_neg(&w6, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S3 -= S7
   if ((e = mp_sub(&w3, &w7, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S5 -= (512*S7)
   if ((e = mp_mul_2d(&w7, 9, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S3 *= 2
   if ((e = mp_mul_2d(&w3, 1, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S3 -= S8
   if ((e = mp_sub(&w3, &w8, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S7 -= S1
   if ((e = mp_sub(&w7, &w1, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S7 -= S9
   if ((e = mp_sub(&w7, &w9, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S8 += S2
   if ((e = mp_add(&w8, &w2, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S5 += S3
   if ((e = mp_add(&w5, &w3, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S8 -= (80*S6)
   if ((e = mp_mul_d(&w6, 80, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w8, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S3 -= (510*S9)
   if ((e = mp_mul_d(&w9, 510, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= S2
   if ((e = mp_sub(&w4, &w2, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S3 *= 3
   if ((e = mp_mul_d(&w3, 3, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S3 += S5
   if ((e = mp_add(&w3, &w5, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S8 /= 180 \\ division by 180
   if ((e = mp_div_d(&w8, 180, &w8, NULL)) != MP_OKAY) {
      goto ERR;
   }
// S5 += (378*S7)
   if ((e = mp_mul_d(&w7, 378, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S2 /= 4
   if ((e = mp_div_2d(&w2, 2, &w2, NULL)) != MP_OKAY) {
      goto ERR;
   }
// S6 -= S2
   if ((e = mp_sub(&w6, &w2, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S5 /= (-72) \\ division by -72
   if ((e = mp_div_d(&w5, 72, &w5, NULL)) != MP_OKAY) {
      goto ERR;
   }
   if (&w5.sign == MP_ZPOS)
      (&w5)->sign = MP_NEG;
   (&w5)->sign = MP_ZPOS;
// S3 /= (-360) \\ division by -360
   if ((e = mp_div_d(&w3, 360, &w3, NULL)) != MP_OKAY) {
      goto ERR;
   }
   if (&w3.sign == MP_ZPOS)
      (&w3)->sign = MP_NEG;
   (&w3)->sign = MP_ZPOS;
// S2 -= S8
   if ((e = mp_sub(&w2, &w8, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S7 -= S3
   if ((e = mp_sub(&w7, &w3, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= (256*S5)
   if ((e = mp_mul_2d(&w5, 8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S3 -= S5
   if ((e = mp_sub(&w3, &w5, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= (4096*S3)
   if ((e = mp_mul_2d(&w3, 12, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= (16*S7)
   if ((e = mp_mul_2d(&w7, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S4 += (256*S6)
   if ((e = mp_mul_2d(&w6, 8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S6 += S2
   if ((e = mp_add(&w6, &w2, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S2 *= 180
   if ((e = mp_mul_d(&w2, 180, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S2 += S4
   if ((e = mp_add(&w2, &w4, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S2 /= 11340 \\ division by 11340
   if ((e = mp_div_d(&w2, 11340, &w2, NULL)) != MP_OKAY) {
      goto ERR;
   }
// S4 += (720*S6)
   if ((e = mp_mul_d(&w6, 720, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S4 /= (-2160) \\ division by -2160
   if ((e = mp_div_d(&w4, 2160, &w4, NULL)) != MP_OKAY) {
      goto ERR;
   }
   if (&w4.sign == MP_ZPOS)
      (&w4)->sign = MP_NEG;
   (&w4)->sign = MP_ZPOS;
// S6 -= S4
   if ((e = mp_sub(&w6, &w4, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S8 -= S2
   if ((e = mp_sub(&w8, &w2, &w8)) != MP_OKAY) {
      goto ERR;
   }
// P = S1*x^8 + S2*x^7 + S3*x^6 + S4*x^5 + S5*x^4 + S6*x^3 + S7*x^2 + S8*x + S9
   if ((e = mp_copy(&w9, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w8, B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w7, 2 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w7, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w6, 3 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w6, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w5, 4 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w5, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w4, 5 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w3, 6 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w2, 7 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w1, 8 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w1, c)) != MP_OKAY) {
      goto ERR;
   }
// P - A*B \\ == zero
   c->sign = sign;
ERR:

ERRb4:
   mp_clear(&b4);
ERRb3:
   mp_clear(&b3);
ERRb2:
   mp_clear(&b2);
ERRb1:
   mp_clear(&b1);
ERRb0:
   mp_clear(&b0);
ERRa4:
   mp_clear(&a4);
ERRa3:
   mp_clear(&a3);
ERRa2:
   mp_clear(&a2);
ERRa1:
   mp_clear(&a1);
ERRa0:
   mp_clear(&a0);

ERR0:

   mp_clear_multi(&w1, &w2, &w3, &w4, &w5, &w6, &w7, &w8, &w9, &tmp1, &tmp2,
                  // &a0, &a1, &a2, &a3, &a4, &b0, &b1, &b2, &b3, &b4,
                  NULL);
   return e;
}
Exemplo n.º 12
0
/* find the n'th root of an integer
 *
 * Result found such that (c)**b <= a and (c+1)**b > a
 *
 * This algorithm uses Newton's approximation
 * x[i+1] = x[i] - f(x[i])/f'(x[i])
 * which will find the root in log(N) time where
 * each step involves a fair bit.  This is not meant to
 * find huge roots [square and cube, etc].
 */
int mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast)
{
   mp_int  t1, t2, t3, a_;
   int     res;

   /* input must be positive if b is even */
   if (((b & 1u) == 0u) && (a->sign == MP_NEG)) {
      return MP_VAL;
   }

   if ((res = mp_init(&t1)) != MP_OKAY) {
      return res;
   }

   if ((res = mp_init(&t2)) != MP_OKAY) {
      goto LBL_T1;
   }

   if ((res = mp_init(&t3)) != MP_OKAY) {
      goto LBL_T2;
   }

   /* if a is negative fudge the sign but keep track */
   a_ = *a;
   a_.sign = MP_ZPOS;

   /* t2 = 2 */
   mp_set(&t2, 2uL);

   do {
      /* t1 = t2 */
      if ((res = mp_copy(&t2, &t1)) != MP_OKAY) {
         goto LBL_T3;
      }

      /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */

      /* t3 = t1**(b-1) */
      if ((res = mp_expt_d_ex(&t1, b - 1u, &t3, fast)) != MP_OKAY) {
         goto LBL_T3;
      }

      /* numerator */
      /* t2 = t1**b */
      if ((res = mp_mul(&t3, &t1, &t2)) != MP_OKAY) {
         goto LBL_T3;
      }

      /* t2 = t1**b - a */
      if ((res = mp_sub(&t2, &a_, &t2)) != MP_OKAY) {
         goto LBL_T3;
      }

      /* denominator */
      /* t3 = t1**(b-1) * b  */
      if ((res = mp_mul_d(&t3, b, &t3)) != MP_OKAY) {
         goto LBL_T3;
      }

      /* t3 = (t1**b - a)/(b * t1**(b-1)) */
      if ((res = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY) {
         goto LBL_T3;
      }

      if ((res = mp_sub(&t1, &t3, &t2)) != MP_OKAY) {
         goto LBL_T3;
      }
   }  while (mp_cmp(&t1, &t2) != MP_EQ);

   /* result can be off by a few so check */
   for (;;) {
      if ((res = mp_expt_d_ex(&t1, b, &t2, fast)) != MP_OKAY) {
         goto LBL_T3;
      }

      if (mp_cmp(&t2, &a_) == MP_GT) {
         if ((res = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) {
            goto LBL_T3;
         }
      } else {
         break;
      }
   }

   /* set the result */
   mp_exch(&t1, c);

   /* set the sign of the result */
   c->sign = a->sign;

   res = MP_OKAY;

LBL_T3:
   mp_clear(&t3);
LBL_T2:
   mp_clear(&t2);
LBL_T1:
   mp_clear(&t1);
   return res;
}
Exemplo n.º 13
0
int main(int argc, char *argv[])
{
  int      ix;
  mp_int   a, b, c, d;
  mp_digit r;
  mp_err   res;

  if(argc < 3) {
    fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]);
    return 1;
  }

  printf("Test 3: Multiplication and division\n\n");
  srand(time(NULL));

  mp_init(&a);
  mp_init(&b);

  mp_read_radix(&a, argv[1], 10);
  mp_read_radix(&b, argv[2], 10);
  printf("a = "); mp_print(&a, stdout); fputc('\n', stdout);
  printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
  
  mp_init(&c);
  printf("\nc = a * b\n");

  mp_mul(&a, &b, &c);
  printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);

  printf("\nc = b * 32523\n");

  mp_mul_d(&b, 32523, &c);
  printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
  
  mp_init(&d);
  printf("\nc = a / b, d = a mod b\n");
  
  mp_div(&a, &b, &c, &d);
  printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);  
  printf("d = "); mp_print(&d, stdout); fputc('\n', stdout);  

  ix = rand() % 256;
  printf("\nc = a / %d, r = a mod %d\n", ix, ix);
  mp_div_d(&a, (mp_digit)ix, &c, &r);
  printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);  
  printf("r = %04X\n", r);

#if EXPT
  printf("\nc = a ** b\n");
  mp_expt(&a, &b, &c);
  printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);  
#endif

  ix = rand() % 256;
  printf("\nc = 2^%d\n", ix);
  mp_2expt(&c, ix);
  printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);

#if SQRT
  printf("\nc = sqrt(a)\n");
  if((res = mp_sqrt(&a, &c)) != MP_OKAY) {
    printf("mp_sqrt: %s\n", mp_strerror(res));
  } else {
    printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
    mp_sqr(&c, &c);
    printf("c^2 = "); mp_print(&c, stdout); fputc('\n', stdout);
  }
#endif

  mp_clear(&d);
  mp_clear(&c);
  mp_clear(&b);
  mp_clear(&a);

  return 0;
}
Exemplo n.º 14
0
  Integer* Integer::from_cstr(STATE, const char* str, const char* end,
                              int base, Object* strict)
  {
    if(base == 1 || base > 36) return nil<Integer>();

    // Skip any combination of leading whitespace and underscores.  Leading
    // whitespace is OK in strict mode, but underscores are not.
    while(isspace(*str) || *str == '_') {
      if(*str == '_') {
        if(CBOOL(strict)) {
          return nil<Integer>();
        } else {
          return Fixnum::from(0);
        }
      }

      str++;
    }

    bool negative = false;

    if(*str == '-') {
      str++;
      negative = true;
    } else if(*str == '+') {
      str++;
    }

    int detected_base = 0;
    const char* str_start = str;

    /* Try to detect a base prefix. We have to do this even though we might
     * have been told the base, we have to know if we should discard the bytes
     * that make up the prefix if it's redundant with the passed in base.
     *
     * For example, if base == 16 and str == "0xa", we return 10.  But if base
     * == 10 and str == "0xa", we fail because we rewind and try to process 0x
     * as part of the base 10 string.
     */
    if(*str == '0') {
      str++;
      switch(*str++) {
      case 'b': case 'B':
        detected_base = 2;
        break;
      case 'o': case 'O':
        detected_base = 8;
        break;
      case 'd': case 'D':
        detected_base = 10;
        break;
      case 'x': case 'X':
        detected_base = 16;
        break;
      default:
        // If passed "017" and a base of 0, that is octal 15.  Otherwise, it
        // is whatever those digits would be in the specified base.
        str--;
        detected_base = 8;
      }
    }

    // If base is less than 0, then it's just a hint for how to process it
    // if there is no base detected.
    if(base < 0) {
      if(detected_base == 0) {
        // Ok, no detected because, use the base hint and start over.
        base = -base;
        str = str_start;
      } else {
        base = detected_base;
      }

    // If 0 was passed in as the base, we use the detected base.
    } else if(base == 0) {

      // Default to 10 if there is no input and no detected base.
      if(detected_base == 0) {
        base = 10;
        str = str_start;

      } else {
        base = detected_base;
      }

    // If the passed in base and the detected base contradict each other, then
    // rewind and process the whole string as digits of the passed in base.
    } else if(base != detected_base) {
      // Rewind the stream and try and consume the prefix as digits in the
      // number.
      str = str_start;
    }

    int max_digits = DIGIT_BIT / digit_bits[base];
    int count = 0;

    int digit = 0;
    mp_digit shift = base, value = 0;
    mp_int a = { 0, 0, 0, 0, 0, };

    for( ; str < end; str++) {
      digit = digit_value[int(*str)];

      if(digit >= 0 && digit < base) {
        if(++count <= max_digits) {
          value = value * base + digit;
        } else {
          if(!mp_isinitialized(&a)) {
            mp_init_set_long(XST, &a, value);
            for(int i = 0; i < max_digits - 1; i++) {
              shift *= base;
            }
          } else {
            mp_mul_d(XST, &a, shift, &a);
            mp_add_d(XST, &a, value, &a);
          }

          value = digit;
          count = 1;
        }

        continue;
      }

      // An underscore is valid iff it is followed by a valid character for
      // this base.
      if(*str == '_') {
        if(!*(str + 1) || *(str + 1) == '_') goto error_check;

        continue;
      }

      if(digit >= base) goto error_check;

      // Consume any whitespace characters.
      if(digit < -1) {
        while(digit_value[int(*++str)] < -1) /* skip whitespace */ ;

        goto error_check;
      }

      // Done parsing.
      break;
    }

error_check:

    if(str < end && CBOOL(strict)) {
      if(mp_isinitialized(&a)) mp_clear(&a);
      return nil<Integer>();
    }

    if(!mp_isinitialized(&a)) {
      if(value < FIXNUM_MAX) {
        Fixnum* result = Fixnum::from(value);
        if(negative) {
          return result->neg(state);
        } else {
          return result;
        }
      }

      mp_init_set_long(XST, &a, value);
    } else {
      shift = base;
      for(int i = 0; i < count - 1; i++) {
        shift *= base;
      }

      mp_mul_d(XST, &a, shift, &a);
      mp_add_d(XST, &a, value, &a);
    }

    if(negative) {
      mp_neg(XST, &a, &a);
    }

    Integer* result = Bignum::from(state, &a);
    mp_clear(&a);

    return result;
  }
Exemplo n.º 15
0
static int muli(void *a, unsigned long b, void *c)
{
   LTC_ARGCHK(a != NULL);
   LTC_ARGCHK(c != NULL);
   return mpi_to_ltc_error(mp_mul_d(a, b, c));
}
/* find the n'th root of an integer 
 *
 * Result found such that (c)**b <= a and (c+1)**b > a 
 *
 * This algorithm uses Newton's approximation 
 * x[i+1] = x[i] - f(x[i])/f'(x[i]) 
 * which will find the root in log(N) time where 
 * each step involves a fair bit.  This is not meant to 
 * find huge roots [square and cube, etc].
 */
int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
{
  mp_int  t1, t2, t3;
  int     res, neg;

  /* input must be positive if b is even */
  if ((b & 1) == 0 && a->sign == MP_NEG) {
    return MP_VAL;
  }

  if ((res = mp_init (&t1)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init (&t2)) != MP_OKAY) {
    goto LBL_T1;
  }

  if ((res = mp_init (&t3)) != MP_OKAY) {
    goto LBL_T2;
  }

  /* if a is negative fudge the sign but keep track */
  neg     = a->sign;
  a->sign = MP_ZPOS;

  /* t2 = 2 */
  mp_set (&t2, 2);

  do {
    /* t1 = t2 */
    if ((res = mp_copy (&t2, &t1)) != MP_OKAY) {
      goto LBL_T3;
    }

    /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
    
    /* t3 = t1**(b-1) */
    if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) {   
      goto LBL_T3;
    }

    /* numerator */
    /* t2 = t1**b */
    if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) {    
      goto LBL_T3;
    }

    /* t2 = t1**b - a */
    if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) {  
      goto LBL_T3;
    }

    /* denominator */
    /* t3 = t1**(b-1) * b  */
    if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) {    
      goto LBL_T3;
    }

    /* t3 = (t1**b - a)/(b * t1**(b-1)) */
    if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) {  
      goto LBL_T3;
    }

    if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) {
      goto LBL_T3;
    }
  }  while (mp_cmp (&t1, &t2) != MP_EQ);

  /* result can be off by a few so check */
  for (;;) {
    if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) {
      goto LBL_T3;
    }

    if (mp_cmp (&t2, a) == MP_GT) {
      if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) {
         goto LBL_T3;
      }
    } else {
      break;
    }
  }

  /* reset the sign of a first */
  a->sign = neg;

  /* set the result */
  mp_exch (&t1, c);

  /* set the sign of the result */
  c->sign = neg;

  res = MP_OKAY;

LBL_T3:mp_clear (&t3);
LBL_T2:mp_clear (&t2);
LBL_T1:mp_clear (&t1);
  return res;
}
Exemplo n.º 17
0
/* squaring using Toom-Cook 3-way algorithm */
int mp_toom_sqr(const mp_int *a, mp_int *b)
{
   mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
   int res, B;

   /* init temps */
   if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
      return res;
   }

   /* B */
   B = a->used / 3;

   /* a = a2 * B**2 + a1 * B + a0 */
   if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
      goto LBL_ERR;
   }

   if ((res = mp_copy(a, &a1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   mp_rshd(&a1, B);
   if ((res = mp_mod_2d(&a1, DIGIT_BIT * B, &a1)) != MP_OKAY) {
      goto LBL_ERR;
   }

   if ((res = mp_copy(a, &a2)) != MP_OKAY) {
      goto LBL_ERR;
   }
   mp_rshd(&a2, B*2);

   /* w0 = a0*a0 */
   if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
      goto LBL_ERR;
   }

   /* w4 = a2 * a2 */
   if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
      goto LBL_ERR;
   }

   /* w1 = (a2 + 2(a1 + 2a0))**2 */
   if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }

   if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
      goto LBL_ERR;
   }

   /* w3 = (a0 + 2(a1 + 2a2))**2 */
   if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }

   if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
      goto LBL_ERR;
   }


   /* w2 = (a2 + a1 + a0)**2 */
   if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
      goto LBL_ERR;
   }

   /* now solve the matrix

      0  0  0  0  1
      1  2  4  8  16
      1  1  1  1  1
      16 8  4  2  1
      1  0  0  0  0

      using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
    */

   /* r1 - r4 */
   if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* r3 - r0 */
   if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* r1/2 */
   if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* r3/2 */
   if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* r2 - r0 - r4 */
   if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* r1 - r2 */
   if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* r3 - r2 */
   if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* r1 - 8r0 */
   if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* r3 - 8r4 */
   if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* 3r2 - r1 - r3 */
   if ((res = mp_mul_d(&w2, 3uL, &w2)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* r1 - r2 */
   if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* r3 - r2 */
   if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* r1/3 */
   if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
      goto LBL_ERR;
   }
   /* r3/3 */
   if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
      goto LBL_ERR;
   }

   /* at this point shift W[n] by B*n */
   if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
      goto LBL_ERR;
   }

   if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
      goto LBL_ERR;
   }
   if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
      goto LBL_ERR;
   }

LBL_ERR:
   mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
   return res;
}
Exemplo n.º 18
0
/* integer signed division. 
 * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
 * HAC pp.598 Algorithm 14.20
 *
 * Note that the description in HAC is horribly 
 * incomplete.  For example, it doesn't consider 
 * the case where digits are removed from 'x' in 
 * the inner loop.  It also doesn't consider the 
 * case that y has fewer than three digits, etc..
 *
 * The overall algorithm is as described as 
 * 14.20 from HAC but fixed to treat these cases.
*/
int mp_div MPA(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
  mp_int  q, x, y, t1, t2;
  int     res, n, t, i, norm, neg;

  /* is divisor zero ? */
  if (mp_iszero (b) == 1) {
    return MP_VAL;
  }

  /* if a < b then q=0, r = a */
  if (mp_cmp_mag (a, b) == MP_LT) {
    if (d != NULL) {
      res = mp_copy (MPST, a, d);
    } else {
      res = MP_OKAY;
    }
    if (c != NULL) {
      mp_zero (c);
    }
    return res;
  }

  if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
    return res;
  }
  q.used = a->used + 2;

  if ((res = mp_init (&t1)) != MP_OKAY) {
    goto LBL_Q;
  }

  if ((res = mp_init (&t2)) != MP_OKAY) {
    goto LBL_T1;
  }

  if ((res = mp_init_copy (MPST, &x, a)) != MP_OKAY) {
    goto LBL_T2;
  }

  if ((res = mp_init_copy (MPST, &y, b)) != MP_OKAY) {
    goto LBL_X;
  }

  /* fix the sign */
  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
  x.sign = y.sign = MP_ZPOS;

  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
  norm = mp_count_bits(&y) % DIGIT_BIT;
  if (norm < (int)(DIGIT_BIT-1)) {
     norm = (DIGIT_BIT-1) - norm;
     if ((res = mp_mul_2d (MPST, &x, norm, &x)) != MP_OKAY) {
       goto LBL_Y;
     }
     if ((res = mp_mul_2d (MPST, &y, norm, &y)) != MP_OKAY) {
       goto LBL_Y;
     }
  } else {
     norm = 0;
  }

  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
  n = x.used - 1;
  t = y.used - 1;

  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
  if ((res = mp_lshd (MPST, &y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
    goto LBL_Y;
  }

  while (mp_cmp (&x, &y) != MP_LT) {
    ++(q.dp[n - t]);
    if ((res = mp_sub (MPST, &x, &y, &x)) != MP_OKAY) {
      goto LBL_Y;
    }
  }

  /* reset y by shifting it back down */
  mp_rshd (&y, n - t);

  /* step 3. for i from n down to (t + 1) */
  for (i = n; i >= (t + 1); i--) {
    if (i > x.used) {
      continue;
    }

    /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 
     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
    if (x.dp[i] == y.dp[t]) {
      q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
    } else {
      mp_word tmp;
      tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
      tmp |= ((mp_word) x.dp[i - 1]);
      tmp /= ((mp_word) y.dp[t]);
      if (tmp > (mp_word) MP_MASK)
        tmp = MP_MASK;
      q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
    }

    /* while (q{i-t-1} * (yt * b + y{t-1})) > 
             xi * b**2 + xi-1 * b + xi-2 
     
       do q{i-t-1} -= 1; 
    */
    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
    do {
      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;

      /* find left hand */
      mp_zero (&t1);
      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
      t1.dp[1] = y.dp[t];
      t1.used = 2;
      if ((res = mp_mul_d (MPST, &t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
        goto LBL_Y;
      }

      /* find right hand */
      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
      t2.dp[2] = x.dp[i];
      t2.used = 3;
    } while (mp_cmp_mag(&t1, &t2) == MP_GT);

    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
    if ((res = mp_mul_d (MPST, &y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
      goto LBL_Y;
    }

    if ((res = mp_lshd (MPST, &t1, i - t - 1)) != MP_OKAY) {
      goto LBL_Y;
    }

    if ((res = mp_sub (MPST, &x, &t1, &x)) != MP_OKAY) {
      goto LBL_Y;
    }

    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
    if (x.sign == MP_NEG) {
      if ((res = mp_copy (MPST, &y, &t1)) != MP_OKAY) {
        goto LBL_Y;
      }
      if ((res = mp_lshd (MPST, &t1, i - t - 1)) != MP_OKAY) {
        goto LBL_Y;
      }
      if ((res = mp_add (MPST, &x, &t1, &x)) != MP_OKAY) {
        goto LBL_Y;
      }

      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
    }
  }

  /* now q is the quotient and x is the remainder 
   * [which we have to normalize] 
   */
  
  /* get sign before writing to c */
  x.sign = x.used == 0 ? MP_ZPOS : a->sign;

  if (c != NULL) {
    mp_clamp (&q);
    mp_managed_copy (MPST, &q, c);
    c->sign = neg;
  }

  if (d != NULL) {
    mp_div_2d (MPST, &x, norm, &x, NULL);
    mp_managed_copy (MPST, &x, d);
  }

  res = MP_OKAY;

LBL_Y:mp_clear (&y);
LBL_X:mp_clear (&x);
LBL_T2:mp_clear (&t2);
LBL_T1:mp_clear (&t1);
LBL_Q:mp_clear (&q);
  return res;
}
Exemplo n.º 19
0
Mpi operator*(mp_digit i, Mpi &a){
	Mpi z;
	if (z.err==MP_OKAY)
		z.err=mp_mul_d(&(a.mpi_n),i,&(z.mpi_n)); 
	return z;
}