예제 #1
0
void bn_add(bn_t c, bn_t a, bn_t b) {
	int sa, sb;

	sa = a->sign;
	sb = b->sign;

	if (sa == sb) {
		/* If the signs are equal, copy the sign and add. */
		c->sign = sa;
		if (bn_cmp_abs(a, b) == CMP_LT) {
			bn_add_imp(c, b, a);
		} else {
			bn_add_imp(c, a, b);
		}
	} else {
		/* If the signs are different, subtract. */
		if (bn_cmp_abs(a, b) == CMP_LT) {
			c->sign = sb;
			bn_sub_imp(c, b, a);
		} else {
			c->sign = sa;
			bn_sub_imp(c, a, b);
		}
	}
}
예제 #2
0
void bn_sub(bn_t c, bn_t a, bn_t b) {
	int sa, sb;

	sa = a->sign;
	sb = b->sign;

	if (sa != sb) {
		/* If the signs are different, copy the sign of the first number and
		 * add. */
		c->sign = sa;
		if (bn_cmp_abs(a, b) == CMP_LT) {
			bn_add_imp(c, b, a);
		} else {
			bn_add_imp(c, a, b);
		}
	} else {
		/* If the signs are equal, adjust the sign and subtract. */
		if (bn_cmp_abs(a, b) != CMP_LT) {
			c->sign = sa;
			bn_sub_imp(c, a, b);
		} else {
			c->sign = (sa == BN_POS) ? BN_NEG : BN_POS;
			bn_sub_imp(c, b, a);
		}
	}
}
예제 #3
0
int bn_cmp(bn_t a, bn_t b) {
	if (a->sign == BN_POS && b->sign == BN_NEG) {
		return CMP_GT;
	}
	if (a->sign == BN_NEG && b->sign == BN_POS) {
		return CMP_LT;
	}

	if (a->sign == BN_NEG) {
		return bn_cmp_abs(b, a);
	}

	return bn_cmp_abs(a, b);
}
예제 #4
0
파일: relic_bn_lcm.c 프로젝트: ekr/hacrypto
void bn_lcm(bn_t c, const bn_t a, const bn_t b) {
	bn_t u, v;

	bn_null(u);
	bn_null(v);

	TRY {
		bn_new(u);
		bn_new(v);

		bn_gcd(u, a, b);

		if (bn_cmp_abs(a, b) == CMP_LT) {
			bn_div(v, a, u);
			bn_mul(c, b, v);
		} else {
			bn_div(v, b, u);
			bn_mul(c, a, v);
		}
		c->sign = BN_POS;
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(u);
		bn_free(v);
	}
}
예제 #5
0
/**
 * Divides two multiple precision integers, computing the quotient and the
 * remainder.
 *
 * @param[out] c		- the quotient.
 * @param[out] d		- the remainder.
 * @param[in] a			- the dividend.
 * @param[in] b			- the the divisor.
 */
static void bn_div_imp(bn_t c, bn_t d, const bn_t a, const bn_t b) {
	bn_t q, x, y, r;
	int sign;

	bn_null(q);
	bn_null(x);
	bn_null(y);
	bn_null(r);

	/* If a < b, we're done. */
	if (bn_cmp_abs(a, b) == CMP_LT) {
		if (bn_sign(a) == BN_POS) {
			if (c != NULL) {
				bn_zero(c);
			}
			if (d != NULL) {
				bn_copy(d, a);
			}
		} else {
			if (c != NULL) {
				bn_set_dig(c, 1);
				if (bn_sign(b) == BN_POS) {
					bn_neg(c, c);
				}
			}
			if (d != NULL) {
				if (bn_sign(b) == BN_POS) {
					bn_add(d, a, b);	
				} else {
					bn_sub(d, a, b);
				}
			}
		}
		return;
	}

	TRY {
		bn_new(x);
		bn_new(y);
		bn_new_size(q, a->used + 1);
		bn_new(r);
		bn_zero(q);
		bn_zero(r);
		bn_abs(x, a);
		bn_abs(y, b);

		/* Find the sign. */
		sign = (a->sign == b->sign ? BN_POS : BN_NEG);

		bn_divn_low(q->dp, r->dp, x->dp, a->used, y->dp, b->used);

		/* We have the quotient in q and the remainder in r. */
		if (c != NULL) {
			q->used = a->used - b->used + 1;
			q->sign = sign;
			bn_trim(q);
			if (bn_sign(a) == BN_NEG) {
				bn_sub_dig(c, q, 1);
			} else {
				bn_copy(c, q);
			}
		}

		if (d != NULL) {
			r->used = b->used;
			r->sign = a->sign;
			bn_trim(r);
			if (bn_sign(a) == BN_NEG) {
				bn_add(d, r, b);
			} else {
				bn_copy(d, r);
			}
		}
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(r);
		bn_free(q);
		bn_free(x);
		bn_free(y);
	}
}
예제 #6
0
void bn_rand_mod(bn_t a, bn_t b) {
	do {
		bn_rand(a, bn_sign(b), bn_bits(b));
	} while (bn_is_zero(a) || bn_cmp_abs(a, b) != CMP_LT);
}