void _elem_frac_poly_divrem(elem_ptr Q, elem_ptr Qden, elem_ptr R, elem_ptr Rden, elem_srcptr A, elem_srcptr Aden, long lenA, elem_srcptr B, elem_srcptr Bden, long lenB, const ring_t ring) { long lenQ = lenA - lenB + 1; long lenR = lenB - 1; long size = ring->size; elem_ptr den; elem_srcptr leadB = SRC_INDEX(B, lenB - 1, size); ulong d; /* TODO: lenB == 1 case efficiently */ _elem_poly_pseudo_divrem(Q, R, &d, A, lenA, B, lenB, ring); for ( ; lenR != 0 && elem_is_zero(SRC_INDEX(R, lenR - 1, size), ring); lenR--); /* TODO: lead^d = +/- 1 and other cases more efficiently */ /* see also fmpq_poly_divrem, which avoids the post-canonicalisation */ ELEM_TMP_INIT(den, ring); elem_pow_ui(den, leadB, d, ring); elem_mul(den, den, Aden, ring); elem_set(Rden, den, ring); elem_set(Qden, den, ring); _elem_vec_scalar_mul(Q, Q, lenQ, Bden, ring); ELEM_TMP_CLEAR(den, ring); }
void elem_mat_set_perm(elem_mat_t X, const long * perm, const elem_mat_t B, const ring_t ring) { long c, i, j, m, n; const ring_struct * ering = RING_PARENT(ring); m = elem_mat_nrows(B, ring); n = elem_mat_ncols(B, ring); if (X == B) { elem_ptr tmp = _elem_vec_init(n, ering); for (c = 0; c < m; c++) { for (i = 0; i < n; i++) elem_set(INDEX(tmp, i, ering->size), elem_mat_entry(B, perm[i], c, ring), ering); for (i = 0; i < n; i++) elem_set(elem_mat_entry(X, i, c, ring), INDEX(tmp, i, ering->size), ering); } _elem_vec_clear(tmp, n, ering); } else { for (i = 0; i < m; i++) for (j = 0; j < n; j++) elem_set(elem_mat_entry(X, i, j, ring), elem_mat_entry(B, perm[i], j, ring), ering); } }
void _elem_poly_sub(elem_ptr res, elem_srcptr poly1, long len1, elem_srcptr poly2, long len2, const ring_t ring) { long i, min; long size = ring->size; if (ring->type == TYPE_FMPZ && 0) { _fmpz_poly_sub(res, poly1, len1, poly2, len2); return; } min = FLINT_MIN(len1, len2); for (i = 0; i < min; i++) elem_sub(INDEX(res, i, size), SRC_INDEX(poly1, i, size), SRC_INDEX(poly2, i, size), ring); if (poly1 != res) for (i = min; i < len1; i++) elem_set(INDEX(res, i, size), SRC_INDEX(poly1, i, size), ring); for (i = min; i < len2; i++) elem_neg(INDEX(res, i, size), SRC_INDEX(poly2, i, size), ring); }
void elem_set(elem_ptr res, elem_srcptr src, const ring_t ring) { if (res != src) { switch (ring->type) { case TYPE_FMPZ: fmpz_set(res, src); break; case TYPE_LIMB: *((mp_ptr) res) = *((mp_srcptr) src); break; case TYPE_MOD: elem_set(res, src, ring->parent); break; case TYPE_POLY: elem_poly_set(res, src, ring); break; case TYPE_FRAC: elem_set(NUMER(res, ring), NUMER(src, ring), RING_NUMER(ring)); elem_set(DENOM(res, ring), DENOM(src, ring), RING_DENOM(ring)); break; case TYPE_COMPLEX: elem_set(REALPART(res, ring), REALPART(src, ring), RING_PARENT(ring)); elem_set(IMAGPART(res, ring), IMAGPART(src, ring), RING_PARENT(ring)); break; default: NOT_IMPLEMENTED("set", ring); } } }
void elem_frac_poly_divrem(elem_ptr Q, elem_ptr R, elem_srcptr A, elem_srcptr B, const ring_t ring) { if (elem_is_zero(B, ring)) { printf("Exception: division by zero in elem_frac_poly_divrem\n"); abort(); } else if (Q == R) { printf("Exception: output arguments Q and R may not be aliased\n"); abort(); } else if (((const elem_poly_struct *) A)->length < ((const elem_poly_struct *) B)->length) { elem_set(R, A, ring); elem_zero(Q, ring); } else if (Q == A || Q == B) { elem_ptr tmp; ELEM_TMP_INIT(tmp, ring); elem_frac_poly_divrem(tmp, R, A, B, ring); elem_swap(Q, tmp, ring); ELEM_TMP_CLEAR(tmp, ring); } else if (R == B) { elem_ptr tmp; ELEM_TMP_INIT(tmp, ring); elem_frac_poly_divrem(Q, tmp, A, B, ring); elem_swap(R, tmp, ring); ELEM_TMP_CLEAR(tmp, ring); } else { /* if the denominators are the same as coefficients, we can do pseudo division */ if (RING_DENOM(ring) == RING_PARENT(RING_NUMER(ring))) { _elem_frac_poly_divrem_wrap(NUMER(Q, ring), DENOM(Q, ring), NUMER(R, ring), DENOM(R, ring), NUMER(A, ring), DENOM(A, ring), NUMER(B, ring), DENOM(B, ring), RING_NUMER(ring), RING_DENOM(ring)); } else { NOT_IMPLEMENTED("polynomial divrem with different denominator type", ring); } } }
void _elem_vec_gcd(elem_ptr res, elem_srcptr vec, long len, elem_srcptr input, const ring_t ring) { long i, size = ring->size; if (len == 0) { elem_set(res, input, ring); } else { elem_gcd(res, vec, input, ring); for (i = 1; i < len && !elem_is_one(res, ring); i++) elem_gcd(res, res, INDEX(vec, i, size), ring); } }
static void layer_index_set(layer_index_t *layer_index, int base_value, int multiple) { layer_index_t *p_layer_index=layer_index; elem_t *p_elem=NULL; int elem_value=0; int which_layer=0; if(NULL==p_layer_index){ return; } while(NULL!=p_layer_index){ ++which_layer; elem_value=calc_elem_value(which_layer,base_value,multiple); p_elem=p_layer_index->elem; while(NULL!=p_elem){ elem_set(p_elem,&elem_value,int_elem_set); p_elem=p_elem->next_elem; } p_layer_index=p_layer_index->next_layer; } return; }
void _elem_poly_gcd_subresultant(elem_ptr res, elem_srcptr poly1, long len1, elem_srcptr poly2, long len2, const ring_t ring) { if (len2 == 1) { _elem_vec_gcd(res, poly1, len1, poly2, ring); } else { elem_ptr a, b, d, g, h; elem_ptr A, B, W; long alloc, lenA, lenB, size = ring->size; alloc = len1 + len2 + 5; W = _elem_vec_init(alloc, ring); A = INDEX(W, 0, size); B = INDEX(A, len1, size); a = INDEX(B, len2, size); b = INDEX(a, 1, size); d = INDEX(b, 1, size); g = INDEX(d, 1, size); h = INDEX(g, 1, size); lenA = len1; lenB = len2; _elem_vec_gcd(a, poly1, lenA, a, ring); _elem_vec_gcd(b, poly2, lenB, b, ring); _elem_vec_scalar_divexact(A, poly1, lenA, a, ring); _elem_vec_scalar_divexact(B, poly2, lenB, b, ring); elem_gcd(d, a, b, ring); elem_one(g, ring); elem_one(h, ring); while (1) { const long delta = lenA - lenB; _elem_poly_pseudo_rem_cohen(A, A, lenA, B, lenB, ring); ELEM_VEC_NORM(A, lenA, ring); if (lenA <= 1) break; { /* Swap A and B */ elem_ptr T; long len; T = A, A = B, B = T, len = lenA, lenA = lenB, lenB = len; } if (delta == 1) { elem_mul(b, g, h, ring); _elem_vec_scalar_divexact(B, B, lenB, b, ring); elem_set(g, SRC_INDEX(A, lenA - 1, size), ring); elem_set(h, g, ring); } else { elem_pow_ui(a, h, delta, ring); elem_mul(b, g, a, ring); _elem_vec_scalar_divexact(B, B, lenB, b, ring); elem_pow_ui(b, SRC_INDEX(A, lenA - 1, size), delta, ring); elem_mul(g, h, b, ring); elem_divexact(h, g, a, ring); elem_set(g, SRC_INDEX(A, lenA - 1, size), ring); } } if (lenA == 1) { elem_set(res, d, ring); _elem_vec_zero(INDEX(res, 1, size), len2 - 1, ring); } else { elem_zero(b, ring); _elem_vec_gcd(b, B, lenB, b, ring); _elem_vec_scalar_divexact(B, B, lenB, b, ring); if (elem_leading_sign(INDEX(B, lenB - 1, size), ring) < 0) elem_neg(d, d, ring); _elem_vec_scalar_mul(res, B, lenB, d, ring); if (len2 >= lenB) _elem_vec_zero(INDEX(res, lenB, size), len2 - lenB, ring); } _elem_vec_clear(W, alloc, ring); } }
void test_divexact(flint_rand_t state, const ring_t ring, const long * size, long iters) { long iter; for (iter = 0; iter < iters; iter++) { elem_ptr A, B, C, Q; A = elem_new(ring); B = elem_new(ring); C = elem_new(ring); Q = elem_new(ring); elem_randtest(A, state, size, ring); elem_randtest_not_zero(B, state, size, ring); elem_mul(C, A, B, ring); elem_divexact(Q, C, B, ring); if (!elem_equal(Q, A, ring)) { printf("FAIL: (A * B) / B = A\n"); ring_print(ring); printf("\n\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(C, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); abort(); } elem_randtest_not_zero(A, state, size, ring); elem_set(B, A, ring); elem_divexact(C, A, A, ring); elem_divexact(Q, A, B, ring); if (!elem_equal(C, Q, ring) || !elem_is_one(Q, ring)) { printf("FAIL: aliasing A, B\n"); ring_print(ring); printf("\n\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(C, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); abort(); } elem_randtest(A, state, size, ring); elem_randtest_not_zero(B, state, size, ring); elem_mul(A, A, B, ring); elem_divexact(Q, A, B, ring); elem_divexact(A, A, B, ring); if (!elem_equal(A, Q, ring)) { printf("FAIL: aliasing Q, A\n"); ring_print(ring); printf("\n\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(C, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); abort(); } elem_randtest(A, state, size, ring); elem_randtest_not_zero(B, state, size, ring); elem_mul(A, A, B, ring); elem_divexact(Q, A, B, ring); elem_divexact(B, A, B, ring); if (!elem_equal(B, Q, ring)) { printf("FAIL: aliasing Q, A\n"); ring_print(ring); printf("\n\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(C, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); abort(); } elem_randtest_not_zero(B, state, size, ring); elem_divexact(Q, B, B, ring); elem_divexact(B, B, B, ring); if (!elem_equal(B, Q, ring)) { printf("FAIL: aliasing Q, A, B\n"); ring_print(ring); printf("\n\n"); elem_print(A, ring); printf("\n\n"); elem_print(B, ring); printf("\n\n"); elem_print(C, ring); printf("\n\n"); elem_print(Q, ring); printf("\n\n"); abort(); } elem_del(A, ring); elem_del(B, ring); elem_del(C, ring); elem_del(Q, ring); } }