示例#1
0
/**
 * @brief Pre-calculate some of the expensive steps in reduction. 
 *
 * This function should only be called once (normally when a session starts).
 * When the session is over, bi_free_mod() should be called. bi_mod_power()
 * relies on this function being called.
 * @param ctx [in]  The bigint session context.
 * @param bim [in]  The bigint modulus that will be used.
 * @param mod_offset [in] There are three moduluii that can be stored - the
 * standard modulus, and its two primes p and q. This offset refers to which
 * modulus we are referring to.
 * @see bi_free_mod(), bi_mod_power().
 */
void ICACHE_FLASH_ATTR bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset)
{
    int k = bim->size;
    comp d = (comp)((long_comp)COMP_RADIX/(bim->comps[k-1]+1));
#ifdef CONFIG_BIGINT_MONTGOMERY
    bigint *R, *R2;
#endif

    ctx->bi_mod[mod_offset] = bim;
    bi_permanent(ctx->bi_mod[mod_offset]);
    ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d);
    bi_permanent(ctx->bi_normalised_mod[mod_offset]);

#if defined(CONFIG_BIGINT_MONTGOMERY)
    /* set montgomery variables */
    R = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k-1);     /* R */
    R2 = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k*2-1);  /* R^2 */
    ctx->bi_RR_mod_m[mod_offset] = bi_mod(ctx, R2);             /* R^2 mod m */
    ctx->bi_R_mod_m[mod_offset] = bi_mod(ctx, R);               /* R mod m */

    bi_permanent(ctx->bi_RR_mod_m[mod_offset]);
    bi_permanent(ctx->bi_R_mod_m[mod_offset]);

    ctx->N0_dash[mod_offset] = modular_inverse(ctx->bi_mod[mod_offset]);

#elif defined (CONFIG_BIGINT_BARRETT)
    ctx->bi_mu[mod_offset] = 
        bi_divide(ctx, comp_left_shift(
            bi_clone(ctx, ctx->bi_radix), k*2-1), ctx->bi_mod[mod_offset], 0);
    bi_permanent(ctx->bi_mu[mod_offset]);
#endif
}
示例#2
0
/**
 * @brief Perform a single montgomery reduction.
 * @param ctx [in]  The bigint session context.
 * @param bixy [in]  A bigint.
 * @return The result of the montgomery reduction.
 */
bigint * ICACHE_FLASH_ATTR bi_mont(BI_CTX *ctx, bigint *bixy)
{
    int i = 0, n;
    uint8_t mod_offset = ctx->mod_offset;
    bigint *bim = ctx->bi_mod[mod_offset];
    comp mod_inv = ctx->N0_dash[mod_offset];

    check(bixy);

    if (ctx->use_classical)     /* just use classical instead */
    {
        return bi_mod(ctx, bixy);
    }

    n = bim->size;

    do
    {
        bixy = bi_add(ctx, bixy, comp_left_shift(
                    bi_int_multiply(ctx, bim, bixy->comps[i]*mod_inv), i));
    } while (++i < n);

    comp_right_shift(bixy, n);

    if (bi_compare(bixy, bim) >= 0)
    {
        bixy = bi_subtract(ctx, bixy, bim, NULL);
    }

    return bixy;
}
示例#3
0
文件: main.c 项目: seppo0010/Euler
int main() {
	bi_initialize();
	bigint sum = int_to_bi(1);
	bigint last = int_to_bi(1);
	int i, j;
	for (i = 1; i <= (SIZE-1)/2; ++i) {
		for (j = 0; j < 4; ++j) {
			last = bi_add(last, bi_int_multiply(int_to_bi(i), 2));
			sum = bi_add(sum, bi_copy(last));
		}
	}
	bi_print(stdout, sum);
	printf("\n");
	bi_free(last);
	bi_terminate();
	return 0;
}
示例#4
0
文件: main.c 项目: seppo0010/Euler
int main() {
	bi_initialize();
	bigint last = int_to_bi(1);
	int i, j;
	int number_of_primes = 0;
	for (i = 1;; ++i) {
		for (j = 0; j < 4; ++j) {
			last = bi_add(last, bi_int_multiply(int_to_bi(i), 2));
			if (j != 3 && bi_is_probable_prime(bi_copy(last), 4)) {
				++number_of_primes;
			}
		}
		if ((double)number_of_primes / (4*i+1) < 0.1) {
			printf("%d\n", i*2+1);
			break;
		}
#ifdef DEBUG
		printf("%d/%d on iteration %d ~%f\n", number_of_primes, (4*i+1), i, (float)number_of_primes/(4*i+1));
#endif
	}
	bi_free(last);
	bi_terminate();
	return 0;
}
示例#5
0
/**
 * @brief Does both division and modulo calculations. 
 *
 * Used extensively when doing classical reduction.
 * @param ctx [in]  The bigint session context.
 * @param u [in]    A bigint which is the numerator.
 * @param v [in]    Either the denominator or the modulus depending on the mode.
 * @param is_mod [n] Determines if this is a normal division (0) or a reduction
 * (1).
 * @return  The result of the division/reduction.
 */
bigint * ICACHE_FLASH_ATTR bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod)
{
    int n = v->size, m = u->size-n;
    int j = 0, orig_u_size = u->size;
    uint8_t mod_offset = ctx->mod_offset;
    comp d;
    bigint *quotient, *tmp_u;
    comp q_dash;

    check(u);
    check(v);

    /* if doing reduction and we are < mod, then return mod */
    if (is_mod && bi_compare(v, u) > 0)
    {
        bi_free(ctx, v);
        return u;
    }

    quotient = alloc(ctx, m+1);
    tmp_u = alloc(ctx, n+1);
    v = trim(v);        /* make sure we have no leading 0's */
    d = (comp)((long_comp)COMP_RADIX/(V1+1));

    /* clear things to start with */
    memset(quotient->comps, 0, ((quotient->size)*COMP_BYTE_SIZE));

    /* normalise */
    if (d > 1)
    {
        u = bi_int_multiply(ctx, u, d);

        if (is_mod)
        {
            v = ctx->bi_normalised_mod[mod_offset];
        }
        else
        {
            v = bi_int_multiply(ctx, v, d);
        }
    }

    if (orig_u_size == u->size)  /* new digit position u0 */
    {
        more_comps(u, orig_u_size + 1);
    }

    do
    {
        /* get a temporary short version of u */
        memcpy(tmp_u->comps, &u->comps[u->size-n-1-j], (n+1)*COMP_BYTE_SIZE);

        /* calculate q' */
        if (U(0) == V1)
        {
            q_dash = COMP_RADIX-1;
        }
        else
        {
            q_dash = (comp)(((long_comp)U(0)*COMP_RADIX + U(1))/V1);

            if (v->size > 1 && V2)
            {
                /* we are implementing the following:
                if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) - 
                        q_dash*V1)*COMP_RADIX) + U(2))) ... */
                comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) - 
                                            (long_comp)q_dash*V1);
                if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2))
                {
                    q_dash--;
                }
            }
        }

        /* multiply and subtract */
        if (q_dash)
        {
            int is_negative;
            tmp_u = bi_subtract(ctx, tmp_u, 
                    bi_int_multiply(ctx, bi_copy(v), q_dash), &is_negative);
            more_comps(tmp_u, n+1);

            Q(j) = q_dash; 

            /* add back */
            if (is_negative)
            {
                Q(j)--;
                tmp_u = bi_add(ctx, tmp_u, bi_copy(v));

                /* lop off the carry */
                tmp_u->size--;
                v->size--;
            }
        }
        else
        {
            Q(j) = 0; 
        }

        /* copy back to u */
        memcpy(&u->comps[u->size-n-1-j], tmp_u->comps, (n+1)*COMP_BYTE_SIZE);
    } while (++j <= m);

    bi_free(ctx, tmp_u);
    bi_free(ctx, v);

    if (is_mod)     /* get the remainder */
    {
        bi_free(ctx, quotient);
        return bi_int_divide(ctx, trim(u), d);
    }
    else            /* get the quotient */
    {
        bi_free(ctx, u);
        return trim(quotient);
    }
}
示例#6
0
文件: main.c 项目: seppo0010/Euler
int main() {
	bi_initialize();
	bigint sum = int_to_bi(0);
	int a,b,c,d,e,f,g,h,i,j;
	int n;
	for (a=9;a>0;--a) {
	for (b=9;b>=0;--b) {
		if (b==a) continue;
	for (c=9;c>=0;--c) {
		if (c==a||c==b) continue;
	for (d=9;d>=0;--d) {
		if (d==a||d==b||d==c) continue;
	for (e=9;e>=0;--e) {
		if (e==a||e==b||e==c||e==d) continue;
	for (f=9;f>=0;--f) {
		if (f==a||f==b||f==c||f==d||f==e) continue;
	for (g=9;g>=0;--g) {
		if (g==a||g==b||g==c||g==d||g==e||g==f) continue;
	for (h=9;h>=0;--h) {
		if (h==a||h==b||h==c||h==d||h==e||h==f||h==g) continue;
	for (i=9;i>=0;--i) {
		if (i==a||i==b||i==c||i==d||i==e||i==f||i==g||i==h) continue;
	for (j=9;j>=0;--j) {
		if (j==a||j==b||j==c||j==d||j==e||j==f||j==g||j==h||j==i) continue;
		if ((b * 100 + c * 10 + d) % 2 == 0)
		if ((c * 100 + d * 10 + e) % 3 == 0)
		if ((d * 100 + e * 10 + f) % 5 == 0)
		if ((e * 100 + f * 10 + g) % 7 == 0)
		if ((f * 100 + g * 10 + h) % 11 == 0)
		if ((g * 100 + h * 10 + i) % 13 == 0)
		if ((h * 100 + i * 10 + j) % 17 == 0) {
			n = 
			    b * 100000000 +
			    c * 10000000 +
			    d * 1000000 +
			    e * 100000 +
			    f * 10000 +
			    g * 1000 +
			    h * 100 +
			    i * 10 +
			    j * 1;
			sum = bi_add(sum, int_to_bi(n));
			sum = bi_add(sum, bi_int_multiply(int_to_bi(1000000000), a));
#ifdef DEBUG
printf("%d%d%d%d%d%d%d%d%d%d\n", a,b,c,d,e,f,g,h,i,j);
bi_print(stdout,bi_copy(sum));
printf("\n");
#endif
		}
	}
	}
	}
	}
	}
	}
	}
	}
	}
	}
	bi_print(stdout,sum);
	printf("\n");
	bi_terminate();
	return 0;
}