integer * integer_sqrt(integer * data) { integer *ret = integer_copy(data); integer *r = integer_copy(data); integer *q = NULL; if (data->sign_of_integer || integer_empty(data)) { integer_destroy(r); return ret; } integer_rshifta(ret, integer_lg(ret) / 2); integer_sdivide(r, ret, &q); while (integer_abscmp(r, ret) < 0) { integer_adda(ret, r); integer_rshifta(ret, 1); integer_destroy(r); r = integer_copy(data); integer_sdivide(r, ret, &q); } integer_destroy(r); integer_destroy(q); return ret; }
// MCA: BinaryGCD int integer_gcd(integer_t gcd, integer_t a, integer_t b) { integer_t u, v; size_t a0, b0, z; u = integer_create(0); v = gcd; a0 = integer_get_trailing_zeros(a); b0 = integer_get_trailing_zeros(b); z = MIN(a0, b0); VERIFY(integer_divide_power_of_two(u, a, a0)); VERIFY(integer_divide_power_of_two(v, b, b0)); VERIFY(integer_absolute_value(u, u)); VERIFY(integer_absolute_value(v, v)); while(!integers_are_equal(u, v)) { if(-1 == integer_compare(u, v)) { SWAP(u, v); } VERIFY(integer_subtract(u, u, v)); VERIFY(integer_divide_power_of_two(u, u, integer_get_trailing_zeros(u))); } VERIFY(integer_multiply_power_of_two(gcd, u, z)); if(u != gcd) { integer_destroy(u); } else { integer_destroy(v); } return 0; }
rational * rational_fromString(char *s) { int i, lenstr; int base = 10; integer *tmp = NULL; rational *ret = (rational *) calloc(sizeof(rational), 1); ret->den = integer_long_init(1L); lenstr = strlen(s); for (; lenstr > 0 && s[lenstr] == ' '; lenstr--); for (i = 0; i < lenstr && s[i] != '/'; i++); if (i < lenstr) { ret->num = integer_fromString(s); integer_destroy(ret->den); ret->den = integer_fromString(s + i + 1); rational_normalize(ret); return ret; } for (i = 0; i < lenstr && (s[i] != ' ' || s[i] == 0); i++); switch (s[i]) { // ���� �� � ���������� �������, � � ������� 0x1234... case 'b': base = 2; break; case 'o': base = 8; break; case 'd': base = 10; break; case 'x': base = 16; break; default: base = 10; } for (i = 0; i < lenstr && s[i] != '.'; i++); if (i < lenstr) { integer_destroy(ret->den); ret->den = integer_long_init(base); integer_powa(ret->den, lenstr - i - 1); ret->num = integer_fromString(s); integer_mula(ret->num, ret->den); tmp = integer_fromString(s + i + 1); integer_adda(ret->num, tmp); integer_destroy(tmp); rational_normalize(ret); return ret; } ret->num = integer_fromString(s); return ret; }
int rational_abscmp(rational * data, rational * y) { int ret; integer *tmp1, *tmp2; tmp1 = integer_copy(data->num); integer_mula(tmp1, y->den); tmp2 = integer_copy(data->den); integer_mula(tmp1, y->num); ret = integer_abscmp(tmp1, tmp2); integer_destroy(tmp1); integer_destroy(tmp2); return ret; }
integer * integer_long_mula(integer * data, long y) { integer *z = integer_long_init(y); integer_mula(data, z); integer_destroy(z); return data; }
integer * integer_long_mul(integer * data, long y) { integer *ret = integer_copy(data); integer *z = integer_long_init(y); integer_mula(ret, z); integer_destroy(z); return ret; }
integer * integer_suba(integer * data, integer * y) { int cmp; integer *q = NULL; if (y->len_of_integer == 0) return data; if (data->len_of_integer == 0) { integer_assign(data, y); return data; } cmp = integer_abscmp(data, y); if (cmp == 0 && data->sign_of_integer == y->sign_of_integer) { integer_clear(data); return data; } if (cmp == 0 && data->sign_of_integer != y->sign_of_integer) { integer_lshifta(data, 1); return data; } if (cmp == 1 && data->sign_of_integer == y->sign_of_integer) { integer_ssub(data, y); return data; } if (cmp == 1 && data->sign_of_integer != y->sign_of_integer) { integer_sadd(data, y); return data; } if (cmp == -1 && data->sign_of_integer == y->sign_of_integer) { q = integer_copy(data); integer_assign(data, y); data->sign_of_integer = !data->sign_of_integer; integer_ssub(data, q); integer_destroy(q); return data; } if (cmp == -1 && data->sign_of_integer == y->sign_of_integer) { integer_sadd(data, y); return data; } return data; }
rational * rational_sqrt(rational * data) { integer *tmp; rational *ret = rational_copy(data); if (integer_realLen(ret->den) < 3) { integer_lshifta(ret->num, 64L); integer_lshifta(ret->den, 64L); } tmp = integer_sqrt(ret->num); ret->num = integer_copy(tmp); integer_destroy(tmp); tmp = integer_sqrt(ret->den); ret->den = integer_copy(tmp); integer_destroy(tmp); rational_normalize(ret); return ret; }
rational * rational_suba(rational * data, rational * a) { integer *tmp; tmp = integer_copy(a->num); integer_mula(data->num, a->den); integer_mula(data->den, a->den); integer_mula(tmp, data->den); integer_suba(data->num, tmp); integer_destroy(tmp); rational_normalize(data); return data; }
int integer_square(integer_t target, integer_t source) { bool aliased; integer_t result; if(integer_is_zero(source)) { return integer_set_unsigned_value(target, 0); } aliased = (result == source); result = aliased ? integer_create(0) : target; VERIFY(GROW(result, 2 * LENGTH(source))); SET_SIGNED_LENGTH(result, 2 * LENGTH(source)); VERIFY(digits_square(DIGITS(result), DIGITS(source), LENGTH(source))); NORMALIZE(result); // TODO: call a karatsuba routine here... if(aliased) { EXCHANGE(target, result); integer_destroy(result); } return 0; }
// MCA: ExtendedGCD int integer_gcd_extended(integer_t gcd, integer_t U, integer_t V, integer_t A, integer_t B) { integer_t a, b, u, w, v, x, q, r; INSIST(gcd != U); INSIST(gcd != V); INSIST(U != V); a = integer_create(0); b = gcd; VERIFY(integer_absolute_value(a, A)); VERIFY(integer_absolute_value(b, B)); u = U; VERIFY(integer_set_unsigned_value(u, 1)); w = integer_create(0); v = V; VERIFY(integer_set_unsigned_value(v, 0)); x = integer_create(1); q = integer_create(0); r = integer_create(0); while(!integer_is_zero(b)) { VERIFY(integer_divide(q, r, a, b)); SWAP(a, b); SWAP(b, r); VERIFY(integer_multiply(r, q, w)); VERIFY(integer_subtract(u, u, r)); SWAP(u, w); VERIFY(integer_multiply(r, q, x)); VERIFY(integer_subtract(v, v, r)); SWAP(v, x); } EXCHANGE(gcd, a); EXCHANGE(U, u); EXCHANGE(V, v); integer_destroy(q); /* gcd is passed between a, b, and r */ if(b == gcd) { integer_destroy(a); integer_destroy(r); } else if(a == gcd) { integer_destroy(b); integer_destroy(r); } else { integer_destroy(a); integer_destroy(b); } /* U and V are passed between u, w and v, x respectively */ if(u == U) { integer_destroy(w); integer_destroy(x); } else { integer_destroy(u); integer_destroy(v); } return 0; }