inline Polynomial<T, Structure>::Polynomial(const Structure *structure, const coefficient_list& coefficients): m_structure (structure), m_coefficients (coefficients) { remove_zeros(); }
number_t mult_number(number_t a, number_t b) { number_t result; int i, k; result = string_to_number("0.0"); for (i = 0; i < b.digit_len; i++) { result = mult_one(10, result); result = add_number(result, mult_one(b.digit[i], a)); } k = b.digit_len - b.int_len; if (result.int_len > k) { result.int_len -= k; } else { for (i = result.digit_len - 1; i >= 0; i--) result.digit[i + k] = result.digit[i]; for (i = 0; i < k; i++) result.digit[i] = 0; result.digit_len += k; } result.sign *= b.sign; return remove_zeros(result); }
inline Polynomial<T, Structure>& Polynomial<T, Structure>::operator-=(const Polynomial<T, Structure>& other) { pad_zeros(other.deg() + 1); subtract(other); remove_zeros(); return *this; }
inline Polynomial<T, Structure>::Polynomial(const Structure *structure, InputIterator begin, InputIterator end): m_structure (structure), m_coefficients (begin, end) { remove_zeros(); }
inline Polynomial<T, Structure> Polynomial<T, Structure>::pow_mod_eq(const LongInt& exponent, const Polynomial<T, Structure>& modulus) { const ring_type *r = ring(); AlgebraHelper::pow_mod_eq(r, *this, exponent, modulus); remove_zeros(); delete r; return *this; }
inline Polynomial<T, Structure>& Polynomial<T, Structure>::operator*=(const Polynomial<T, Structure>& other) { coefficient_list new_coefficients (deg() + other.deg() + 1, 0); for (size_type i = 0; i <= deg(); ++i) { for (size_type j = 0; j <= other.deg(); ++j) { new_coefficients[i + j] += m_coefficients[i] * other.m_coefficients[j]; } } m_coefficients = new_coefficients; remove_zeros(); return *this; }
static cl_object prepare_ratio_to_float(cl_object num, cl_object den, int digits, cl_fixnum *scaleout) { /* We have to cook our own routine because GMP does not round. * The recipe is simple: we multiply the numberator by a large * enough number so that the division by the denominator fits * the floating point number. The result is scaled back by the * appropriate exponent. */ /* Scale down the denominator, eliminating the zeros * so that we have smaller operands. */ cl_fixnum scale = remove_zeros(&den); cl_fixnum num_size = ecl_integer_length(num); cl_fixnum delta = ecl_integer_length(den) - num_size; scale -= delta; { cl_fixnum adjust = digits + delta + 1; if (adjust > 0) { num = ecl_ash(num, adjust); } else if (adjust < 0) { den = ecl_ash(den, -adjust); } } do { const cl_env_ptr the_env = ecl_process_env(); cl_object fraction = ecl_truncate2(num, den); cl_object rem = ecl_nth_value(the_env, 1); cl_fixnum len = ecl_integer_length(fraction); if ((len - digits) == 1) { if (ecl_oddp(fraction)) { cl_object one = ecl_minusp(num)? ecl_make_fixnum(-1) : ecl_make_fixnum(1); if (rem == ecl_make_fixnum(0)) { if (cl_logbitp(ecl_make_fixnum(1), fraction) != ECL_NIL) fraction = ecl_plus(fraction, one); } else { fraction = ecl_plus(fraction, one); } } *scaleout = scale - (digits + 1); return fraction; } den = ecl_ash(den, 1); scale++; } while (1); }
number_t sub_number(number_t a, number_t b) { number_t r; int borrow, dif, i, t, m; r = zero(); if ((a.sign < 0) || (b.sign < 0)) { b.sign *= -1; r = add_number(a, b); return r; } if (compare_number(a, b) < 0) { r = sub_number(b, a); r.sign = -1; return r; } r.int_len = max(a.int_len, b.int_len); m = max(a.digit_len - a.int_len, b.digit_len - b.int_len); r.digit_len = r.int_len + m; borrow = 0; for (i = r.digit_len - 1; i >= 0; i--) { dif = -borrow; t = i - r.int_len + a.int_len; if (t < a.digit_len && t >= 0) dif += a.digit[t]; t = i - r.int_len + b.int_len; if (t < b.digit_len && t >= 0) dif -= b.digit[t]; if (dif < 0) { borrow = 1; dif += 10; } else borrow = 0; r.digit[i] = dif % 10; } return remove_zeros(r); }
number_t mult_one(char d, number_t a) { number_t result; int carry, s, i; result.digit_len = a.digit_len + 1; result.int_len = a.int_len + 1; result.sign = a.sign; carry = 0; for (i = a.digit_len - 1; i >= 0; i--) { s = a.digit[i] * d + carry; result.digit[i + 1] = s % 10; carry = s / 10; } result.digit[0] = carry; return remove_zeros(result); }
number_t mult_num(number_t a, number_t b) { number_t r, tmp; int i, j, t; r = zero(); t = b.digit_len - b.int_len; for (i = b.digit_len - 1, j = 0; i >= 0; i--, j++) { tmp = mult_one(b.digit[i], a); tmp = digit_shift(j, tmp); r = add_number(r, tmp); } r.int_len -= t; r.sign = a.sign * b.sign; return remove_zeros(r); }
number_t mult_one(char b, number_t a) { number_t r; int carry, s, i; r = zero(); r.digit_len = a.digit_len + 1; r.int_len = a.int_len + 1; carry = 0; for (i = a.digit_len - 1; i >= 0; i--) { s = a.digit[i] * b + carry; r.digit[i + 1] = s % 10; carry = s / 10; } r.digit[0] = carry; r.sign = a.sign; return remove_zeros(r); }
//============================================================================== void multiply(const expansion& a, double b, expansion& product) { // basic idea: // multiply each entry in a by b (producing two new entries), then // two_sum them in such a way to guarantee increasing/non-overlapping output product.resize(2*a.size()); if(a.empty()) return; two_product(a[0], b, product[1], product[0]); // finalize product[0] double x, y, z; for(unsigned int i=1; i<a.size(); ++i){ two_product(a[i], b, x, y); // finalize product[2*i-1] two_sum(product[2*i-1], y, z, product[2*i-1]); // finalize product[2*i], could be fast_two_sum instead fast_two_sum(x, z, product[2*i+1], product[2*i]); } // multiplication is a prime candidate for producing spurious zeros, so // remove them by default remove_zeros(product); }
number_t sub_number(number_t a, number_t b) { number_t result; int borrow, dif, i; if (a.sign != b.sign) { b.sign *= -1; return add_number(a, b); } if (a.sign < 0 && b.sign < 0) { a.sign = b.sign = 1; return sub_number(b, a); } if (compare_number(a, b) < 0) { result = sub_number(b, a); if (! (result.digit_len == 2 && result.digit[0] == 0 && result.digit[1] == 0)) result.sign = -1; return result; } result.sign = 1; result.int_len = max(a.int_len, b.int_len); result.digit_len = result.int_len + max(a.digit_len - a.int_len, b.digit_len - b.int_len); borrow = 0; for (i = result.digit_len - 1; i >= 0; i--) { dif = -borrow + digit_at(a, result.int_len - i - 1) - digit_at(b, result.int_len - i - 1); if (dif < 0) { borrow = 1; dif += 10; } else borrow = 0; result.digit[i] = dif % 10; } return remove_zeros(result); }
number_t add_number(number_t a, number_t b) { number_t result; int sum, carry, i; if (a.sign != b.sign) { b.sign *= -1; return sub_number(a, b); } result.sign = a.sign; result.int_len = max(a.int_len, b.int_len) + 1; result.digit_len = result.int_len + max(a.digit_len - a.int_len, b.digit_len - b.int_len); carry = 0; for (i = result.digit_len - 1; i >= 0; i--) { sum = carry + digit_at(a, result.int_len - i - 1) + digit_at(b, result.int_len - i - 1); result.digit[i] = sum % 10; carry = sum / 10; } return remove_zeros(result); }
number_t add_number(number_t a, number_t b) { number_t r; int sum, carry, i, m, t; r = zero(); if (a.sign == b.sign) r.sign = a.sign; else { if (a.sign < 0) { a.sign = 1; r = sub_number(b, a); } else { b.sign = 1; r = sub_number(a, b); } return r; } carry = 0; r.int_len = max(a.int_len, b.int_len) + 1; m = max(a.digit_len - a.int_len, b.digit_len - b.int_len); r.digit_len = r.int_len + m; for (i = r.digit_len - 1; i >= 0; i--) { sum = carry; t = i - r.int_len + a.int_len; if (t < a.digit_len && t >= 0) sum += a.digit[t]; t = i - r.int_len + b.int_len; if (t < b.digit_len && t >= 0) sum += b.digit[t]; r.digit[i] = sum % 10; carry = sum / 10; } return remove_zeros(r); }
void remove_leading_zeros() { remove_zeros(s.begin(), s.end()); }
void remove_trailing_zeros() { remove_zeros(s.rbegin(), s.rend()); }
inline Polynomial<T, Structure>& Polynomial<T, Structure>::operator--() { --m_coefficients[0]; remove_zeros(); return *this; }